/*
* Recréation de la commande LS
* TP/TP de Système
*  alex, DUT Année Spéciale, IUT NANCY Charlemagne (2006)
*/

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

#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <time.h>
#include <grp.h>

int main ( int argc , char ** argv )
{
   //  Déclarations
   DIR * rep_courant ;
   struct dirent * entree ;
   char * nom ;
   char modeFichier = '-' ;
   char modeFinFichier = ' ' ;
   char chemin [ 256 ] ;
   char esc = 27 ;
   char couleur [ 7 ] ;
   char rst [ ] = "[0m" ;
   struct stat statinfo ;
   int sommeBlocs ;
   int tailleBloc ;
   char * droits [ ] = { "---" , "--x" , "-w-" , "-wx" , "r--" , "r-x" , "rw-" , "rwx" } ;
   int b ;

   // Lecture des paramètres passés sur la ligne de commande

   if ( argc < 2 )
       strcpy ( chemin , "." ) ;
   else
       strcpy ( chemin , argv [ 1 ] ) ;


   // Ouvre le répertoire courant
   if ( ( rep_courant = opendir ( chemin ) ) == NULL )
   {
           // Si il n'a pas été possible de l'ouvrir, on sort sur une erreur
           printf ( "Impossible d'ouvrir le répertoire %s\n" , argv [ 1 ] ) ;
           exit ( 2 ) ;
   }


   sommeBlocs = 0 ;
   tailleBloc = 0 ;

   // Parcoure la liste des entrées figurant dans ce répertoire
   while ( entree = readdir ( rep_courant ) )
   {
       //Récupère le nom du fichier
       nom = entree -> d_name ;

       //S'il ne commence pas par un point (fichiers cachés sous unix)
       if ( nom [ 0 ] != '.' )
       {
           //Regarde les informations sur le fichier
           b = lstat ( nom , & statinfo ) ;

           //Détermine le mode du fichier

           //un fichier ordinaire ?
           if ( S_ISREG ( statinfo . st_mode ) )
           {
               modeFichier = '-' ;

               //Fichier exécutable ?
               if (
                       ( statinfo . st_mode & S_IXUSR )
                    || ( statinfo . st_mode & S_IXGRP )
                    || ( statinfo . st_mode & S_IXOTH )
                  )
               {
                   modeFinFichier = '*' ;
                   strcpy ( couleur , "[1;32m" ) ;
               }
               else
               {
                   modeFinFichier = ' ' ;
                   strcpy ( couleur , "[0m" ) ;

               }

           }

           //un répertoire ?
           if ( S_ISDIR ( statinfo . st_mode ) )
           {
               modeFichier = 'd' ;
               modeFinFichier = '/' ;
               strcpy ( couleur , "[1;34m" ) ;
           }

           //un périphérique en mode caractère ?
           if ( S_ISCHR ( statinfo . st_mode ) )
           {
               modeFichier = 'c' ;
               modeFinFichier = '/' ;
               strcpy ( couleur , "[33m" ) ;
           }

           //un périphérique en mode bloc ?
           if ( S_ISBLK ( statinfo . st_mode ) )
           {
               modeFichier = 'b' ;
               modeFinFichier = ' ' ;
               strcpy ( couleur , "[33m" ) ;
           }

           //FIFO (tube nommé) ?
           if ( S_ISFIFO ( statinfo . st_mode ) )
           {
               modeFichier = 'p' ;
               modeFinFichier = '|' ;
               strcpy ( couleur , "[1;35m" ) ;
           }

           //un lien symbolique ?
           if ( S_ISLNK ( statinfo . st_mode ) )
           {
               modeFichier = 'l' ;
               modeFinFichier = '@' ;
               strcpy ( couleur , "[1;36m" ) ;
           }

           //une socket ?
           if ( S_ISSOCK ( statinfo . st_mode ) )
           {
               modeFichier = 's' ;
               modeFinFichier = '=' ;
               strcpy ( couleur , "[1;35m" ) ;
           }


           sommeBlocs += statinfo . st_blocks ;

           if ( tailleBloc == 0 )
               tailleBloc = statinfo . st_blksize ;


           //Affiche les infos sur le fichier (format long de la commande ls)

           printf ( "%c%s%s%s %d %s %s %-4d\t%d-%02d-%02d %02d:%02d %c%s%s%c%s%c\n" ,

                   modeFichier ,                                   //Mode de fichier (répertoire, lien, régulier, ...)
                   droits [ ( statinfo . st_mode ) >> 6 & 7 ] ,    //Droits de l'utilisateur
                   droits [ ( statinfo . st_mode ) >> 3 & 7 ] ,    //Droits du groupe
                   droits [ ( statinfo . st_mode ) >> 0 & 7 ] ,    //Droits du reste du monde

                   statinfo . st_nlink ,                           //Nombre de liens matériels

                   ( getpwuid ( statinfo . st_uid ) ) -> pw_name , //Nom (en clair) de l'utilisateur
                   ( getgrgid ( statinfo . st_gid ) ) -> gr_name , //Nom (en clair) du groupe

                   statinfo . st_size  ,                           //Taille du fichier

                   1900 + ( localtime ( & ( statinfo . st_mtime ) ) ) -> tm_year , //Année de dernière modification
                      1 + ( localtime ( & ( statinfo . st_mtime ) ) ) -> tm_mon  , //Mois de dernière modification
                          ( localtime ( & ( statinfo . st_mtime ) ) ) -> tm_mday , //Jour de dernière modification
                          ( localtime ( & ( statinfo . st_mtime ) ) ) -> tm_hour , //Heure de dernière modification
                          ( localtime ( & ( statinfo . st_mtime ) ) ) -> tm_min  , //Minutes de dernière modification
                   esc, couleur,                                   //La séquence d'échappement suivi de la couleur pour le fichier
                   nom ,                                           //Nom du fichier
                   esc, rst ,                                      //La séquence d'échappement de réinitialisation des couleurs
                   modeFinFichier                                  //Le caractère ajouté à la fin du fichier

                  ) ;

       } //Fin if

   } //Fin while

   closedir ( rep_courant ) ; //Ferme le répertoire

   printf ( "Total : %d\ntaille bloc : %d\n" , sommeBlocs , tailleBloc ) ;

   return 0 ;
}