You are not logged in.
/* ================================================================================================
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
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
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
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
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
If you're using C, why not either use libalpm instead of system(pacman...), or add the functionality to pacman itself (-Qqi)?
[git] | [AURpkgs] | [arch-games]
Offline
you can also scan the files directly, /var/lib/pacman/local it'd prolly be easier as well
Offline
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