Monday, April 20, 2009

Joomla v1.5 and Google Adsense

If you have a website built using joomla (version 1.5) and want to place google adsense ads there, there are modules available. But I wanted an easier native joomla solution. So I hacked up one myself. The main problem with joomla and placing the adsense code is, joomla filters out the script or treats them as html text.

To work around this issue you need to think outside of joomla. Here is what I did.

1) Created a new module using mod_html
2) Noted down the id of the module.
3) Logged in to the backend mysql database and put the adsense code in the module I just created. This way I bypassed all the filtering.

use <joomla_database> ;

update jos_modules set content = '<script type="text/javascript"><!--
google_ad_client = "pub-xxxxxxxxxxxxxxx";

google_ad_slot = "xxxxxxxxxxx";
google_ad_width = 180;
google_ad_height = 150;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>' where id = <module_id> ;


Just remember not to edit this module again from Joomla!

Saturday, April 18, 2009

Unicode utf-8 in Mysql,perl DBI,MIME::Lite

I have a database which stores unicode text. Periodically I need to get the stored text and mail to a mailing list. Initially the text received through the mail was unreadable. After several tries and spending sometime multiple documentation pages, I found all the right settings.

For the mysql DBI you have specifically enable utf8 processing of the strings. There are other ways to achieve this like converting each string. But it will quickly become tedious. This is the easiest.


use DBI;
my $dbh = DBI->connect("DBI:mysql:${database}:${hostname}", $username, $password)
or die "DB Connection not made: $DBI::errstr";
$dbh->{'mysql_enable_utf8'} = 1;
$dbh->do('SET NAMES utf8');


For sending the mail, you tell MIME::Lite the charset(utf8) and encoding(8bit).


my $msg = MIME::Lite->build(
From => 'user@sample.com',
To => $recipient_emailid,
Subject => "=?UTF-8?B?" .
encode("utf-8", $subject) ."?=",
Type => 'TEXT',
Encoding=> '8bit',
Charset => 'utf-8',
Data => $body
);
$msg->attr("content-type.charset" => "utf-8");

$msg->send;

Thursday, December 04, 2008

Specifying your own keytab file for MIT kerberos Library

Use this environment variable to specify a different keytab file for your application. By default it looks for /etc/krb5.keytab.

KRB5_KTNAME=[path to keytab file]

Friday, July 13, 2007

Writing Audio CDs in Linux

I used to reboot my dual boot machine to login to Windows just because I wanted to write some audio CDs to play in my car. But off late I'm putting extra effort not to leave Linux and go to Windows. So I set out to write my own Nero replacement for audio CDs. This is what I came up with. I have been using it for a while and it works flawlessly for me. You might need to make few modifications to suite your needs.



#! /bin/sh

#
# Make an audio CD out of the given mp3 files.
# Author :
# Fri Jul 13 13:15:19 CDT 2007
#

MODE="TAO"
DEVICE="ATA:0,0,0"
TMPDIR=/tmp/audio

if [ ! -d ${TMPDIR} ]; then
mkdir ${TMPDIR}
fi

# don't do rm * at /
cd ${TMPDIR}
if [ $? -eq 0 ]; then
rm -rf ${TMPDIR}/*
fi

while getopts m:d: opt
do
case "$opt" in
m) MODE="$OPTARG";;
d) DEVICE="$OPTARG";;
\?) echo "Usage: $0 [-m T/D] [-d ] <input files>\n"
echo -e "\t -m : CD write Mode : D - DAO/T - TAO ( Default is TAO )"
echo -e "\t -d : CD device to use"
exit 2;;
esac
done
shift $(($OPTIND-1))

if [ $# -eq "0" ]; then
echo "Usage: $0 [-m tao/dao] [-d ] <audio files>\n"
echo -e "\t -m : CD write Mode : D - DAO/T - TAO ( Default is TAO )"
echo -e "\t -d : CD device to use"
exit
fi

echo "Copying files to work area and Removing spaces from file names..."
for i in $*
do
if [ ! -f "$i" ]; then
echo "Couldn't find the file [${i}]. Perhaps the file has spaces and you didn't quote t
hem? "
exit
fi
FILE_N=`echo "$i" | tr ' ' '_'`
TARGET_FILE=`basename ${FILE_N}`
cp "$i" ${TARGET_FILE}
done

echo "Converting mp3 files to wav files..."
for i in *;
do
echo "$i"
mpg321 --rate 44100 --stereo --buffer 3072 --resync -w `basename $i`.wav $i;
done

echo "Normalizing Audio.i.e. Adjusting the volumes..."
#normalize-audio -m *.wav
normalize -m *.wav


if [ ${MODE} == "DAO" ]; then
# if DAO mode, create the TOC and then
# write to CD
echo "Generating TOC for DAO mode"
DAOTOC_FILE="/tmp/toc_cd.toc"
echo CD_DA > ${DAOTOC_FILE}
echo >> ${DAOTOC_FILE}
for fff in *.wav
do
echo -e "TRACK AUDIO\nAUDIOFILE \"${fff}\" 0\n" >> ${DAOTOC_FILE}
done
echo "--------------------------------"
cat ${DAOTOC_FILE}
echo "--------------------------------"
echo "Writing to CD...DAO mode"
cdrao write --device ${DEVICE} ${DAOTOC_FILE}
else
# if TAO we can now write to cd
echo "Writing to CD...TAO mode"
cdrecord -v dev=${DEVICE} -audio -pad *.wav
fi



I would be happy if you drop a note if you find it useful.

Wednesday, June 20, 2007

Converting video files into PSP format

I have lot of video files(songs/home videos) in my computer. I was trying to convert them into a format playable in PSP. After lot of failed attempts the following settings worked for me. Note the -sameq option makes the output file large. But I like the fact that the output has almost the same quality as the source. Here is the script I use now to convert the file to PSP format after that you can copy the *.MP4 and *.THM files to the video folder of PSP.


#! /bin/sh


#
# Convert the input video file into a format suitable
# for playing in sony PSP
# Author :
# Date : Wed Jun 20 12:13:28 CDT 2007
#


# Restrictions
# BIT_RATE <= 768 kbps
# Up to 320×240 or up to 368×208
# Up to 30 fps
# H.264 Main Profile up to Level 2.1
# Up to 2 reference frames
# LC AAC audio up to 48kHz (Media Manager uses 128kbps)


CROP=0
OUTPUT_FILE=M4V00001


while getopts i:c:o: opt
do
case "$opt" in
i) INPUT_FILE="$OPTARG";;
c) CROP="$OPTARG";;
o) OUTPUT_FILE="$OPTARG";;
\?) echo "Usage: $0 -i [-c ] [-o put file>]\n"
exit 2;;
esac
done

if [ ! ${INPUT_FILE} ]; then
echo "Usage: $0 -i [-c ] [-o le>]\n"
exit
fi

ffmpeg -i "$INPUT_FILE" -f psp -r 29 -croptop ${CROP} -cropbottom ${CROP} -sameq -b 768 -ar
24000 -ab 64 -s 368x208 ${OUTPUT_FILE}.MP4

ffmpeg -y -i "$1" -f image2 -ss 5 -vframes 1 -s 160x120 -an ${OUTPUT_FILE}.THM

Wednesday, March 21, 2007

Upgrading from Fedora 5 to Fedora 6 over the net

So far whenever I try to update my linux systems I always do a fresh install. I have my home and data partitions seperate from the root partition. So except for few configuration files which I backup I don't have anything to preserve and a fresh install is the least troublesome way to upgrade.

But I'm deeply bothered about writing few CD's and throw them away once the installation is complete. Hence this time I tried to the upgrade without reintall and without any CD's.

First I made the system clean and up to date.

yum update
yum clean all


Then I forced the update of fedora release packages.

rpm -Uhv http://download.fedora.redhat.com/pub/fedora/linux/core/6/i386/os/Fedora/RPMS/fedora-release-6-4.noarch.rpm
http://download.fedora.redhat.com/pub/fedora/linux/core/6/i386/os/Fedora/RPMS/fedora-release-notes-6-3.noarch.rpm


Since I modified the repo files the rpm installation deposited the repo files as .rpmnew. So I backed up the old files and moved the rpmnew files to the appropriate names. I had livna repo also. So next I moved that repo from release 5 to 6.

yum remove livna-release-5
rpm -ivh http://rpm.livna.org/livna-release-6.rpm


At this point I crossed my finger and ran yum update.


yum update


It found tons of packages to upgrade and a few to uninstall and few more to fresh install. But it also found few dependency issues mostly with gtls package depency tree. So I had to uninstall tons of packages including kde and gnome ( yeah I have both on my machine ;) ). I created a text file of those uninstalled packages with entries like this(cut and paste from yum output).

file /tmp/uninstalled.yum.lst :


GraphicsMagick x86_64 1.1.7-7.fc5 installed 8.2 M
ImageMagick x86_64 6.2.5.4-4.2.1.fc5.7 installed 11 M
ImageMagick-c++ x86_64 6.2.5.4-4.2.1.fc5.7 installed 470 k
NetworkManager-gnome x86_64 0.6.4-1.fc5 installed 403 k
control-center x86_64 1:2.14.2-1 installed 7.7 M
cups x86_64 1:1.2.8-1.fc5 installed 8.7 M
cups-libs x86_64 1:1.2.8-1.fc5 installed 311 k
dvdauthor x86_64 0.6.11-4.lvn5 installed 309 k
eel2 x86_64 2.14.3-1.fc5 installed 1.2 M
eel2-devel x86_64 2.14.3-1.fc5 installed 225 k
ekiga x86_64 2.0.1-5 installed 11 M
eog x86_64 2.14.3-1.fc5 installed 2.2 M
evince x86_64 0.5.1-4 installed 2.2 M
evolution-data-server x86_64 1.6.3-2.fc5 installed 11 M
........


Now "yum update" went fine with out any complains. Unfortunately for some strange reason it also installed i386 packages. Mine is AMD64 and I prefer only x86_64 packages. Again I created a list like the one above and gave it to yum to uninstall.


yum list | grep i386 | grep installed | awk '{print $1}' | xargs > /tmp/i386.lst
yum erase `/tmp/i386.lst`


Now I'm back to the list of packages I unistalled. Again I piped the list to yum this time I asked it to do the installation instead.


cat /tmp/uninstalled.yum.lst | awk '{print $1}' > /tmp/install.txt
yum `cat /tmp/install.txt`


Now I should have the functional system. Wait the infamous nvidia driver. I installed that too...and then rebooted the machine. Everything came up without any problem. I had to fix few inode issues so rebooted again this time logged in a single user mode ( 1 or softlevel=single in grub kernel config line) and ran fsck -y.

So there you go I made a diskless over the internet upgrade of fedora 5 to fedora 6 and I'm still alive to tell the story. My system is working fine so far with out any problems.

Saturday, March 17, 2007

Power Saving - turnoff hard disks after an idle time

I have 1 IDE and 4 SATA disks on my server. Each SATA drive mostly serve one function. One drive for photos, another one for music etc. Though this is a file server, the disks are not used when we are away from home which is a good portion of the day. So I searched ways to reduce power and general hard disk usage. "hdparm" came to rescue in the form of -S option. Here is what man page has to say about -S option.

-S
Set the standby (spindown) timeout for the drive. This value is used by the drive to determine how long to wait (with no disk activity) before turning off the spindle motor to save power. Under such circumstances, the drive may take as long as 30 seconds to respond to a subsequent disk access, though most drives are much quicker. The encoding of the timeout value is somewhat peculiar. A value of zero means "timeouts are disabled": the device will not automatically enter standby mode. Values from 1 to 240 specify multiples of 5 seconds, yielding timeouts from 5 seconds to 20 minutes. Values from 241 to 251 specify from 1 to 11 units of 30 minutes, yielding timeouts from 30 minutes to 5.5 hours. A value of 252 signifies a timeout of 21 minutes. A value of 253 sets a vendor-defined timeout period between 8 and 12 hours, and the value 254 is reserved. 255 is interpreted as 21 minutes plus 15 seconds. Note that some older drives may have very different interpretations of these values.


So I executed the following commands.


hdparm -S60 /dev/hda
hdparm -S60 /dev/sda
hdparm -S60 /dev/sdb
hdparm -S60 /dev/sdc
hdparm -S60 /dev/sdd


And had to make few configuration changes to smartd ( to make it perform the checks less frequently )


/dev/sda -d ata -H -m root -s (S/../.././02|L/../../7/04)
/dev/sdb -d ata -H -m root -s (S/../.././02|L/../../7/04)
/dev/sdc -d ata -H -m root -s (S/../.././02|L/../../7/04)
/dev/sdd -d ata -H -m root -s (S/../.././02|L/../../7/04)


Yes there is a small delay when first navigate to any of the disks. But I'm willing to pay the penalty for the power saving and far quieter machine.

Thursday, March 01, 2007

boost::tokenizer and streams

I had to parse a huge file and build some lookup tables based on that. Each line had a comma seperated fields with white spaces. Initially some "performance" minded person wrote aperl script which writes out c++ function which statically populate the lookup tables. The compiler took literally an hour to compile that file (whose size was ~ 1MB). So I set out to write a small parser and populate the lookup fields. So I read each line and used boost tokenizer to split the comma seperated value. It looked something like this...

while( f.getline(str) )
{
typedef boost::tokenizer<boost::char_separator<char>>
tokenizer;
boost::char_separator<char> sep("\t, ", "\n");
tokenizer tokens(str, sep);
for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
}


The initial version worked. But seeing the constructor for boost::tokenizer I got curious and thought what if I passed the the stream iterator to tokenizer? That would make my code much prettier and it is obviously a better way of doing it. So I did this.

{
std::ifstream ifile(filename.c_str());
std::istream_iterator<char> file_iter(ifile);
std::istream_iterator<char> end_of_stream;

typedef boost::tokenizer<boost::char_separator<char>,
std::istream_iterator<char> >
tokenizer;
boost::char_separator<char> sep("\t, ", "\n");

tokenizer tokens(file_iter,end_of_stream, sep);

for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
}


Soon I hit a snag. For some reason I'm not seeing the "newline" characters which are supposed to be printed since I specifically instruct the tokenizer to keep the "newline" delimeters. That could mean only one thing...The stream iterator is eating up the "\n"s. Ofcourse it is..duh..! Forgot the locales? So I changed to istreambuf_iterator which won't do any parental controls over the stream and show me everything...

{
std::ifstream ifile(filename.c_str());
std::istreambuf_iterator<char> file_iter(ifile);
std::istreambuf_iterator<char> end_of_stream;

typedef boost::tokenizer<boost::char_separator<char>,
std::istreambuf_iterator<char> >
tokenizer;

boost::char_separator<char> sep("\t, ", "\n");

tokenizer tokens(file_iter,end_of_stream, sep);

for (tokenizer::iterator tok_iter = tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << "<" << *tok_iter << "> ";
}


I got what I wanted. A token parser which could parse a stream. Now the stream could be any stream and it will work. And yeah...it takes only few seconds to compile this program and building the lookup table is actually faster than the statically populated version ( because of all the temporary storage the compiler has to allocate and deallocate in the static version ) .

Monday, November 20, 2006

Firefox speedup

I have a cable modem with the screaming download rate. My machine is also have 2Gig of RAM for the firefox to hog. Still I found the pages taking their own time to load. With some help from google I changed some of the configuration in firefox. Type about:config in the address bar. I change the following setting and the changed values are shown.

network.http.pipelining true
network.http.proxy.pipelining true
network.http.max-connections 64
network.http.max-connections-per-server 32
network.http.max-persistent-connections-per-proxy 12
network.http.max-persistent-connections-per-server 6



After this most of the pages load in a flash. Ofcourse these settings are not for everybody. I have the CPU and memory to live with this setting. It may or may not work for you. So use it with caution.

Tuesday, September 26, 2006

Is it a 'char' or 'unsigned char' or 'signed char'?

I inherited a overly-loaded code something like this...

void func(boost::int8_t p)
{
std::cout << "boost::int8_t" << std::endl;
}
void func(boost::uint8_t p)
{
std::cout << "boost::uint8_t" << std::endl;
}
void f1(boost::int16_t s)
{
std::cout << "boost::int16_t" << std::endl;
}
void f1(boost::uint16_t s)
{
std::cout << "boost::uint16_t" << std::endl;
}
main()
{
short sh;
char c;
f1(sh);
func(c);
}


I tried to compile the above code but the compiler is refusing to proceed balking at "func(c)", while it is completely happy with f1(sh). For the uninitiated boost types are typedef-ed to the appropriate platform types like int8_t -> signed char uint8_t -> unsigned char.

It turned out that the language does not specify whether variables of type char are signed or unsigned quantities. So the compiler complains about the func(c) call because it is ambiguous. Whereas f1(sh) succeeds.

Changind the "char c" to "unsigned char" or "signed char" resolves the ambiguity and calms down the compiler. Curiously even forcing the compiler with -funsigned-char didn't help in this case.

Well my philosophy of solving any problem by an extra level of indirection also didn't work. I tried something like this...


template
void func_char_resolver(T c);

template<>
void func_char_resolver(boost::int8_t c) { /// dealing with singed char....
}

template<>
void func_char_resolver(boost::uint8_t c) { /// dealing with unsinged char....
}
void func(char c)
{
func_char_resolver(c);
}


I don't know may be because `char' is a distinct type (of undefined sign) hence none of the specializations matched. Oh well!

Friday, September 22, 2006

ssh error in locking authority file!

While ssh-ing to one of my remote machines I got this error and X forwarding kept failing because of thsi.

/usr/bin/X11/xauth: error in locking authority file

Who would have guessed the problem? I'm running out of my disk quota! It is a weird way of warning about quota over run! 'quota -v' did confirm the theory and after killing few MB's the problem indeed go away!

Wednesday, September 20, 2006

Problems with X11 Composite Extension

When I enabled trancelucency in my KDE the composite manager crashed with the
message asking to insert the following lines in xorg.conf.

Section "Extensions"
Option "Composite" "Enable"
EndSection

And so I did and forgot about it for a week. Last week when I tried to launch
gnucash it wouldn't . It cried something like this.

-------
Gdk-CRITICAL **: file gdkwindow.c: line 1406 (gdk_window_get_visual):
assertion `window != NULL' failed.

Gdk-CRITICAL **: file gdkcolor.c: line 57 (gdk_colormap_new): assertion
`visual != NULL' failed.
SESSION_MANAGER=tcp/pdm1:53739

Gdk-CRITICAL **: file gdkwindow.c: line 1406 (gdk_window_get_visual):
assertion `window != NULL' failed.

Gdk-CRITICAL **: file gdkcolor.c: line 57 (gdk_colormap_new): assertion
`visual != NULL' failed.
Gdk-ERROR **: BadDrawable (invalid Pixmap or Window parameter)
serial 47 error_code 9 request_code 132 minor_code 5
Gdk-ERROR **: BadDrawable (invalid Pixmap or Window parameter)
serial 48 error_code 9 request_code 55 minor_code 0
--------

I thought one of yum update screwed it up. So I looked through the recent
update logs and couldn't find anything remotely connected to gnucash , X11,
gdk or my window manager. Frustrated like hell I stopped thinking about this
problem. I couldn't do my accounting for a week!

It wasn't until I tried to launch one more app which failed with the same
exception. I then started digging deep and found that the culprit was the
Composite extension option. So I disabled the following from xorg.conf

#Section "Extensions"
#Option "Composite" "Enable"
#EndSection

and yes I did my accounts immediately!

Friday, September 08, 2006

Kerberos on 64bit Linux with gcc 4.0

I was trying to compile kerberos on a 64 bit linux (CentOS). First I was getting configure errors about res_search(). Then I downloaded the latest and the greatest v5-1.5.1 from mit and tried to compile with gcc version 4.0. First the configure script was using the old compiler. So I need to teach it to use the gcc4. So I did...


export CC=gcc4
export CXX=g++4


After this configure script went fine. But the compilation was producing some errors like the following in the kadmin/test directory.

tcl_ovsec_kadm.c:85: `Tcl_HashEntry' undeclared (first use in this function)
tcl_ovsec_kadm.c:85: (Each undeclared identifier is reported only once
tcl_ovsec_kadm.c:85: for each function it appears in.)
tcl_ovsec_kadm.c:85: `entry' undeclared (first use in this function)
tcl_ovsec_kadm.c:93: warning: implicit declaration of function `Tcl_InitHashTable'
tcl_ovsec_kadm.c:93: `TCL_STRING_KEYS' undeclared (first use in this function)
tcl_ovsec_kadm.c:105: warning: implicit declaration of function`Tcl_CreateHashEntry'
tcl_ovsec_kadm.c:109: warning: implicit declaration of function `Tcl_SetHashValue'



Looks like I'm not alone -> http://mailman.mit.edu/pipermail/kerberos/2004-September/006391.html
So I followed it faitfully like this and everything went fine.

./configure --prefix=/home/test/krb5 --without-tcl

Tuesday, August 22, 2006

Getting the gcc/g++ compiler #define-s

I was doing 64 bit migration and wanted to know more about gcc/g++ compiler #define-s. One of my friend Homolka Richard gave me a very nice tip. Alias the whole thing!


alias whatg++='echo "main(){}" | g++ -E -x c++ -dM - '
alias whatgcc='echo "main(){}" | gcc -E -x c -dM - '


So running whatg++ from now on will list all the compiler #define-s something like this...


#define __HAVE_BUILTIN_SETJMP__ 1
#define __unix__ 1
#define unix 1
#define __i386__ 1
#define __SIZE_TYPE__ unsigned int
#define __ELF__ 1
#define __GNUC_PATCHLEVEL__ 3
#define __linux 1
#define __unix 1
#define __linux__ 1
#define __USER_LABEL_PREFIX__
#define linux 1
#define __STDC_HOSTED__ 1
#define __EXCEPTIONS 1
#define __GXX_WEAK__ 1
#define __WCHAR_TYPE__ long int
#define __gnu_linux__ 1
#define __WINT_TYPE__ unsigned int
#define __GNUC__ 3
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 3
#define __GXX_ABI_VERSION 102
#define i386 1
#define __GNUC_MINOR__ 2
#define __STDC__ 1
#define __PTRDIFF_TYPE__ int
#define __tune_i386__ 1
#define __REGISTER_PREFIX__
#define __NO_INLINE__ 1
#define _GNU_SOURCE 1
#define __i386 1
#define __VERSION__ "3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)"

Wednesday, August 16, 2006

IMAP through SSL using pine

I have a unix/mail account on a external BSD server. Being a great fan of text mode I use fetchmail to retrieve the mails to my local linux machine and run elm or pine depending on my mood. But my mail server being too restictive on the smtp side, I couldn't hit reply on my local machine and send a reply or send a new mail. Relaying was denied. I could have used a different smtp server of course. But I wanted a simple solution.

So I setup pine on my local machine to do IMAP to my server and things are suddenly rosier. My local copy of pine works on the IMAP folders on my server. I only do fetchmail once in a week for archiving purposes.

The pine configuration is really simple...
Goto "Setup"->"Configuration"
Set 'inbox-path' to
'{mail.foo.com/ssl}INBOX'. Since my server requires a ssl connection todo IMAP.

If your server doesn't support ssl you can replace "ssl" with "notls". I also set the smtp-server to
mail.foo.com

Sunday, August 13, 2006

Making firefox java plug-in work on AMD64

It is frustrating not have the firefox java plugin for AMD64. So living with that handicap for almost a year...finaly I decided to put a end to it.

With little browsing I found the black-down java distribution supports the 64 bit java plugin. I downloaded the distribution from here.

After downloading I executed the installer

sh j2re-1.4.2-03-linux-amd64.bin

This creates a subdirectory "j2re1.4.2". Move this to /usr/java

sudo mv j2re1.4.2 /usr/java/

Now create a softlink to the java plugin from firefox plugins directory...

ln -s /usr/java/j2re1.4.2/plugin/amd64/mozilla/libjavaplugin_oji.so /usr/lib64/mozilla/plugins/

Restart firefox and type "about:plugins" to confirm proper installation.

Thursday, July 20, 2006

bc and awk

I had to calculate sum of a particular column from a huge data file. So I wrote a small bc script like this

----sum.bc-----
sum = 0
while(1)
{
c = read()
if ( c == q )
{
break
}
sum += c
}
sum
quit
----sum.bc-----

and invoked it like this

cat data.dat | awk -F '"' '{print $24}END{print "q"}' | bc -q -l sum.bc

This worked perfectly on my home system which is a linux. But when I did the same in Solaris which had a older bc that dude didn't understand my modern lingo. So I had to abandon the bc script.

So I thought I will just produce the entire sum string with numbers and "+" signs and pump it to bc, like this.

cat data.dat | awk -F '"' '{print $24}' | awk '{printf "%s+",$1}END{print "0"}' | bc -l

Again this worked with my small sample file but bc ran out of internal space when I fed a huge data file. Finally I had to abandon the specialized tool for calculation and fall back on my usual file processor awk to take over the job of the calculator.

cat data.dat | awk -F '"' '{print $24}' | awk '{s += $1}END{print s}'

Well..well ...I fed more than a Gig of data to this small wonder in that old dinky Solaris machine and it worked like a charm.

Tuesday, July 18, 2006

Sendmail and its aversion to upper case

I know lower case rules the Unix world. But at my home for some weird issue with samba shares I had to create a user with upper case "Bob". And I created my fetchmailrc with a very simple no nonsense configuration.

poll mail.X.org proto pop3
user bobnap is Bob here
options keep ssl

When I asked fetchmail to do its job, it did everything correctly and handed over the fetched mail to my local sendmail. Which puked on everything with the following message...

1 message for at mail.X.org (774 octets).
reading message bobnap@mail.X.org:1 of 1 (774 octets) fetchmail: SMTP error: 550 5.1.1 ... User unknown
fetchmail: mail from MAILER-DAEMON@localhost bounced to bobnap@X.org
fetchmail: can't even send to Bob!
not flushed

Intrigued by this I tried to mail myself. The mail ended dead in the "dead.letter".

$ mailx -s "Tot" Bob < /dev/null
Null message body; hope that's ok
$ /home/Bob/dead.letter... Saved message in /home/Bob/dead.letter

I checked and rechecked my sendmail configuration, its aliases etc. Everything seemed alright. Then I logged in as a another user "naper" in my system and tried mailx. Magically everything worked great. Then only I realized the fact that sendmail didn't like the upper case in "Bob" and to confirm that I just edited the passwd files to make it all lower case and sure enough...bob is getting his mails now!

What a strange ugly little devil!

Tuesday, June 27, 2006

SIGCHLD

While I was trying to write a Process Monitoring "Process" for my current employer ( well actually it is Process Monitoring Daemon ) I was breaking my head for almost 1 hour before figuring out what is really going on. I knew SIGCHLD is ignored by default. But I was under impression since I block the signal and wait on that signal specifically I should get the signal. Well it turns out that I won't. You won't either...! You need to specifically install a signal handler before sigwaiting on SIGCHLD. If you remove the sigaction from the below program the while(1) loop will never get to see the SIGCHLD when a child terminates.


#include
#include
#include

static void handle_signal(int signum)
{
printf("got signal %d", signum);
}


main()
{
sigset_t sig_set;
struct sigaction sa;
int signum;
int status;
int pid;
pthread_t tsig;


sa.sa_handler=handle_signal;
sa.sa_flags=0;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);

pthread_sigmask(SIG_BLOCK, &sig_set, NULL);

pid = fork();
if ( pid == 0 ) {
if (execve( "test.sh",
NULL,NULL ) < 0) {
perror("execve");
}
} else {
while (1) {
sigwait(&sig_set,&signum);
if ( signum == SIGCHLD ) {
int pid = wait(&status);
}
}
}
}

Wednesday, June 21, 2006

C# Documentation using Doxygen

C# has its own document generator which generates XML documentation from source code comments. But I'm a C++ guy for the most part
of my life and grew up with Doxygen. So I tried Doxygen on a small C# project.

Here is the configuration file I started with

csdoxy.conf
-----------
PROJECT_NAME = "GA C# Port"
OUTPUT_DIRECTORY = html
WARNINGS = YES
INPUT = mysuperprojectdir
FILE_PATTERNS = *.cs
PERL_PATH = /tp/bin/perl
SEARCHENGINE = NO

And I invoked doxygen just giving the above configuration file.

doxygen csdoxy.conf
The C# project had the M$ recommended way of source documentation. It was OK for the most part. But still the result was not what I
expected. Then I came across this C# input filter.
I downloaded it and saved in the same place where I had the configuration file and added these two lines to the configuration
file

INPUT_FILTER = "python doxyfilter.py"
FILTER_SOURCE_FILES = YES

and the world is a much better place now!