You are not logged in.

#1 2009-05-13 02:20:33

ljshap
Member
From: Ossining, NY
Registered: 2008-01-23
Posts: 160

compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

 

 /* ================================================================================================
REVISED May 14, 2009
REWRITTEN - to check for buffer overuns
Dumb utility which takes the output of pacman -Qi(e) and creates a tab delineated text file 
showing the program name, description and file size, one program per line to be read
with a text editor or spreadsheet.

compiling -> q++ qi.cpp -o qi

Program can be run either as:

qi // which creates:
        pacQi.txt  //  output of pacman -Qi > pacQi.txt
        pacQi.xls  //  tab delineated text file of all installed programs.

or

pacman -Qie > somefile
qi somefile   // which creates 
        somefile.xls // A tab delineated text file of explicitly installed programs

==================================================================================================== */

#include <iostream> 
#include <fstream>
#include <stdlib.h>
#include <cstring>
#include <string>

using namespace std;

string formatstr(const string ="",  char=' ' , int prec=0, int strlength=0 );
int findString ( string, string );
string padString ( string, int,char = ' ') ;

const int progWidth   = 25 ; 
const int descWidth   = 60 ;
const int sizeWidth   = 25 ;
const int cstring_buffer = 100;

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

  char   ch ;                        
  unsigned int findPos=0, start, len ; 
  char sourceFileName[cstring_buffer];
  char targetFileName[cstring_buffer];
  string strLine;
  string progName, progDesc, progSize;

  if (argc ==  1 )                    // no arguments provided creates pacQi.txt
    {
      strncpy(sourceFileName,"pacQi.txt", 12);
      strncpy (targetFileName, "pacQi.xls",12 );
      system ("pacman -Qi > pacQi.txt");
    }
  else                                   // user supplied name 
    {
      len = strlen(argv[1] ) + 6 ;
      if (len > cstring_buffer )
    {
    cout << "\n\nProgram Exiting to Prevent Buffer Overrun\n\n";
    exit (0);
    }
      //cout << endl << argv[1]<< "  length is : " << strlen(argv[1]) << endl;           // testing
      strncpy (sourceFileName,argv[1], strlen(argv[1])  +  2 ) ;
      strncpy (targetFileName,argv[1], cstring_buffer  - 10 ) ;
      strncat (targetFileName,".xls",5);
    }

  ifstream ifile (sourceFileName) ;
  ofstream ofile (targetFileName) ;

  progName ="";
  progDesc = "";
  progSize = "";

  while (ifile.good() )
    {
      getline(ifile,strLine);
      findPos = findString ("Name", strLine);                  // Find Name Line
      if (findPos > 0 )
    {
      for (start=findPos+2; start < strLine.size();start++)
        {
          ch = strLine[start];
          progName = progName +  ch;
        }
      progName = padString(progName,progWidth);
      progDesc="";                  // remove remants of progDesc second line
      progSize="";
    }
      
      findPos = findString ("Size", strLine);                  // Find Size
      if (findPos > 0 )
    {
      for (start=findPos+2; start < strLine.size();start++)   // kill trailing K

        {
          ch = strLine[start];
          if ( ( (ch >= '0') and (ch <= '9') )or (ch == '.')  ) 
        progSize = progSize +  ch;
        }
      
      string temp;
      temp ="";
      progSize = formatstr(progSize, ' ' , 3, 25);
    }
      
      findPos = findString ("Description", strLine);        // Find Description
      if (findPos > 0 )
    {
      for (start=findPos+2; start < strLine.size();start++)
        {
          ch = strLine[start];
          progDesc = progDesc +  ch;
        }
      progDesc=padString(progDesc,descWidth);
    }
      if (progName>"" and progDesc>"" and progSize>"")
    {
      ofile << progName << '\t' << progDesc << '\t' << progSize <<endl ;  // Print program record
      progName ="";
      progDesc = "";
      progSize = "";
    }
    }              // while loop

  ifile.close();
  ofile.close();

}      // E N D   M A I N

//==================================================================================
int findString ( string source, string target) // if source found returns ":" + 2
{
  int found;

  string test;
  test = source;
  
  found = target.find(source);
  if (!found  )
    {
      found = target.find(":");
    }

  if (found < 0 )
    found =0;
  return found;
}
//========================================================================
string padString ( string str, int num, char ch)
{
  string temp;
  int len;
  temp = str;
  len = str.size();

  for (int start = len; start < num; start++)
    temp += ch;
  
  return temp;

}
//===========================================================================
string formatstr(const string str,  char leadchar, int prec, int strlength)
{

  using namespace std;

  int i1,i2,len;
  int sptr,tptr,wholeDigits=0,fracDigits=0;
  int fracPtr=0;
  int noc,commaptr;                         //Number Of Comma's
  bool hasDec=false, isNeg =false;
  string temp,temp2,fracStr,wholeStr,s;

  s=str;
  len=s.size();                             // Length of String w/o '-' sign
  temp="";
  if (str[0]=='-')
    {
      isNeg=true;                           // If negative kill minus sign
      for (int i1=1;i1< len ; i1++ )        // Copy rest of string to s
    temp=temp + str[i1];
      s = temp;
    }

  len=s.size();    
  for (sptr=0;sptr <len;sptr++)               //Find # of digits wholeDigits + in decimal
    {   
    if  (s[sptr]!='.')
      wholeDigits++;
    else
      {
    fracPtr=sptr;
    hasDec=true;
    wholeDigits=sptr ;               // Represents digits before dec  since sptr is at dec. don't increment
    fracDigits = (len-(fracPtr));    // Back into # of decimal digits
    break;
      }
    }
fracStr="";

 if (hasDec)
   for (i1=fracPtr;i1<len;i1++)               // Build fracStr
     fracStr=fracStr + s[i1];

 temp = "";                                   // bugaboo caused by negativity
 for (sptr=wholeDigits-1,tptr=0; sptr>=0 ;sptr--,tptr++ )   //Reverse wholeDigitsing w/o decimal 
   temp= temp + s[sptr];
 
 temp2="";                                           // commatize reversed string to temp2
 commaptr=0;
 noc = temp.size() / 3 ;                       //           S E E IF W O R K S
 for (sptr=0;sptr<wholeDigits;sptr++)
   {
     if (commaptr==3 && noc)
       {
     temp2=temp2 + ',';
     noc--;
     commaptr=0;
       }
     temp2=temp2 + temp[sptr];
     commaptr++;
   }
 
 temp="";                                             // Reverse commatized Reversed String (wtf)
 for (sptr=temp2.size() -1 ; sptr >= 0 ; sptr--)
   temp = temp + temp2[sptr];
 
 s=temp;
   
 len =fracStr.size(); 
 if (prec < 0) 
   ;                                         // Put string back
  
 if (prec == 0 )                             // Leave out fractional part
   fracStr=""; 

  if (prec > 0 )
    { 
      temp="";
      
    if (fracDigits > prec)                 // Will Truncate decimal not round up
      {
        for (int i1=0;i1<=prec;i1++)
          temp=temp + fracStr[i1] ;
        fracStr=temp;
      }
      if (fracDigits < prec +1 && len >0)               //fractDigits include '.' 
    {
      for (int i1=1;i1< (prec-len+2);i1++)
        fracStr=fracStr + '0';
    }

      if(len==0)
    {
      fracStr='.';
      for (int i1=1; i1 <= prec; i1++)
        fracStr = fracStr + '0';
    }
      
    }

  s=s+fracStr;
  
  temp =  "  " ;
  temp[0]=leadchar;
  temp= temp + s;
    
  if (isNeg)
    temp = '(' + temp + ')';

  i1=temp.size();

  temp2="";
  if (strlength > 0 )                        // Pad String for strlength
    {
      i2=strlength -i1;
      for (i1=0;i1<i2;i1++)
    temp2=temp2+' ';
      temp = temp2 + temp;
    }
    
   s =  temp;

   return s;
}

Last edited by ljshap (2009-05-14 16:53:51)


Live Free or Die !

Offline

#2 2009-05-13 10:09:25

dimigon
Member
Registered: 2009-03-07
Posts: 139
Website

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

I have not looked at the code, but I've noticed that you are using strcpy without explicit checking on a user controlled buffer. This makes the program vulnerable to buffer overflow attacks.

Last edited by dimigon (2009-05-13 17:31:47)

Offline

#3 2009-05-13 14:36:27

ljshap
Member
From: Ossining, NY
Registered: 2008-01-23
Posts: 160

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

dimigon wrote:

I have not looked at the code, but I've noticed that you are using strcpy without explicit checking on a user controlled buffer. This make the program vulnerable to buffer overflow attacks.

Thanks

I purposely made my cstring arrays way too big to avoid buffer overuns, but I was not aware that it was a potential security problem.
I added my_strcpy and my_strcat as "wrappers" for strcpy and strcat which hopefully prevents buffer overuns.

Eventhough nobody might be interested, I edited my original post with the new code.

Obviously I'm only an amateur !

Thanks again


Live Free or Die !

Offline

#4 2009-05-13 17:21:55

dimigon
Member
Registered: 2009-03-07
Posts: 139
Website

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

ljshap wrote:
dimigon wrote:

I have not looked at the code, but I've noticed that you are using strcpy without explicit checking on a user controlled buffer. This make the program vulnerable to buffer overflow attacks.

Thanks

I purposely made my cstring arrays way too big to avoid buffer overuns, but I was not aware that it was a potential security problem.
I added my_strcpy and my_strcat as "wrappers" for strcpy and strcat which hopefully prevents buffer overuns.

Eventhough nobody might be interested, I edited my original post with the new code.

Obviously I'm only an amateur !

Thanks again

If you do a sizeof on a pointer for example (char buf[32]; char *ptr = buf; printf("%zu\n", sizeof(ptr));) you get the size of the pointer not the size of the original array. You can use strncpy to ensure that only the required number of bytes are read into the destination array. I'd suggest to read the manpage for strncpy as it is subtle to use sometimes. Using standard functions simplify programming and minimize the risk of introducing bugs in a program.

Last edited by dimigon (2009-05-13 17:33:29)

Offline

#5 2009-05-14 17:02:57

ljshap
Member
From: Ossining, NY
Registered: 2008-01-23
Posts: 160

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

dimigon wrote:

I have not looked at the code, but I've noticed that you are using strcpy without explicit
If you do a sizeof on a pointer for example (char buf[32]; char *ptr = buf; printf("%zu\n", sizeof(ptr));) you get the size of the pointer not the size of the original array. You can use strncpy to ensure that only the required number of bytes are read into the destination array. I'd suggest to read the manpage for strncpy as it is subtle to use sometimes. Using standard functions simplify programming and minimize the risk of introducing bugs in a program.

Your first post did NOT embarrish me, but the second one did.  As soon as I saw it, I said "Oh Shucks" because I was aware of it but just forgot.  I should have been using strlen and not sizeof.
I rewrote it removing the my_strcpy and my_strcat wrappers, using strncpy and strncat instead.

Thanks


Live Free or Die !

Offline

#6 2009-05-15 14:51:51

Daenyth
Forum Fellow
From: Boston, MA
Registered: 2008-02-24
Posts: 1,244

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

If you're using C, why not either use libalpm instead of system(pacman...), or add the functionality to pacman itself (-Qqi)?

Offline

#7 2009-05-15 20:02:10

kumyco
Member
From: somewhere
Registered: 2008-06-23
Posts: 153
Website

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

you can also scan the files directly, /var/lib/pacman/local it'd prolly be easier as well

Offline

#8 2009-05-16 02:59:34

ljshap
Member
From: Ossining, NY
Registered: 2008-01-23
Posts: 160

Re: compact output of pacman -Qi(e) showing only prog,desc,size 1 per line

Daenyth wrote:

If you're using C, why not either use libalpm instead of system(pacman...), or add the functionality to pacman itself (-Qqi)?

I never heard of libalpm, but I'll look into for my own information.
If I added the functionality to pacman itself (assuming i knew how), I would have to change the source and recompile every time there was an update.  My program should work with new versions unless there is a major change to the output of pacman -Qi(e).

My "program" produces the following output format:

52dec                              liba52 is a free library for decoding ATSC A/52 streams.                          207.860
aalib                                AAlib is a portable ASCII art GFX library                                                           824.000
abiword                           A fully-featured word processor                                                                 12,833.000
abiword-plugins            Various plugins for Abiword                                                                           4,199.000

     
  It can be read with a regular text editor or a spreadsheet where it can be sorted by size if you want to see whats taking up hardrive space without scrolling through the detailed output of pacman -Qi.

Obviously, the program has extremely limited usefullness unless you just want to to see installed programs, it description and size in a more compact format either out of curiousity or your planning on reinstalling but want to see the descrition as well as the program name.

I appologize if this functionality is already available in libalpm or elsewhere, but I figured I'd put it up in case anyone wanted it.

Thanks for the additional information.


Live Free or Die !

Offline

Board footer

Powered by FluxBB