Ubuntu user? Debian user? Bash fan? Then you cannot resist yourself using bash_completion. Isn’t it?

ls -<tab>
get all the options!

mplayer -vo <tab>
all available video drivers! Wow!

mencoder -ovc <tab>
all available video encoders!

cat –n<tab>
Oh yes! –number is the switch for printing line numbers as well.

git <tab>
I can do this all with GIT!

And so on… We use them every minute. Lets turn on to see what bash does under the hood…
For that, look at this sample script of AnXa

 
_anxa()
{
local cur prev opts
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
list=$(addr search | grep -v === | grep -v ^Address\ Book | grep -v ^Database | grep -v ^NICK | cut -f 1 -d ' ' | xargs)
opts="-old "$list
 
if [[ ${cur} == * ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
 
complete -F _anxa sms

=> Last line says, call function _anxa to complete command “sms”.
=> Apart from the black words, the important command used is compgen. Which does the magic.

To understand, run
$ compgen -W “-abc -abcd -ab -pqr -pq” — “-pq”
-pqr
-pq

So, the former parameter is the list used to complete the word, and latter argument is what user has typed till now.
If i give,

$ compgen -W “-abc -abcd -ab -pqr -pq” — “-a”
-abc
-abcd
-ab

Simple isn’t that? So you too can make such script of your favorite command that you use very often, by writing a function in any file in /etc/bash_completion.d/
All you need to do is, get the arguments in $opts and use the above sample :-)

compgen -W “-abc -abcd -ab -pqr -pq” — “-a”
-abc
-abcd
-ab

Post to Twitter Tweet This Post

ViM and Macros

20 Nov 2009 In: Programming, ViM, linux

For those who believe marcros are only for Emacs, let me clear your doubts. ViM has a great support for macro..
(Please do note, the original editor Vi DOES NOT have support for macros, it was ViM that introduced macros in it, it is therefore a misconception to many Emacs users that ViM does not have macros)

So quickly intoducing macro..
In simple a macro is any sequence of keys that repeat. And believe me, after learning a quick way to record macros, you’ll really simplify your life.

To explain how can you do all this with ViM, I am taking an example… Lets say you have comments in few lines(not necessarily continuous) of C code of type //
Now old style C does not have // as comments, and you are supposed to run your code on some very backward compiler. So you need to convert all 1877 comments in that file to /* test */
Now you know one way is regex. Other is ViM macros..

An extract of code can be(say)…

int main () { //comment one
int i = 1; //init var
int b;
int c;   // No comment after c
// placed comment at random position, so that regex is now difficult
print ( “test” );
:
:

// and so on

Now to replace all the comments to /* */ you’ll do it just one time(called as recording of macro) in a way that the key strokes you used gets re executed(called playing of macro) and u get the work done.

To start, place the cursor at the start of the first line. And Start recording.. by qa (recording macro in register a, it can be b, c… )

#1 Find the commentRemember all the actions and commands of Vi can be used. Try to keep it generalized. (command mode)
/\/\/

#2 Move one step ahead (right arrow or l (command mode))
l

#3 Now you are at second slash. replace this with * as r* (command mode) to make // as /*
r*

#4 Reach till end of the line, // comments has property that once they start, ends only at the EOL. Key: $ (command mode)
$

#5 Append */ either by directly going in insert mode using ‘a’ or ‘i’ followed by right arrow, then type */ and ESC
a */ ESC

#6 Optionally move to next line
j

Now, stop the recording by pressing ESC q.

Cool enough? Its more cooler to play it..
Press @a and see the next comment getting converted :-)

To convert next 1877 comments, 1877@a (In general n@a, where n is the number of times to repeat the macro)

Thats all to get to going with macros. Go play..

Post to Twitter Tweet This Post

From the time (about 3yrs from now) I started using databases, I was completely using MySQL loyally and never thought of anything else. As I kept on with it, I under gone with the development of some lightweight application. One of such creation is AnXa . This utility can send SMS from command line and is powerfull enough for storing and managing lists and address-book. This is also powered by MySQL. So, the point I am trying to bring is, such things DOES NOT require high end database engines like MySQL.

Why not MySQL for small apps?
1. Dependency. Running MySQL server instance on desktop is a straight NO NO for end-user. And doing remote communication is also a NO NO for desktop users.
2. We never require such power for just address books, right?

In short, we are trying to cut a cake with a sword!

For these basic things and even bigger things, SQLite is there.

Where can you use SQLite?
* For small apps, SQLite is portable, means you can just have it in any small application that require persistent storage than creating your own routines. This will be faster than flat files and provide high-availability.
* While you are in development mode, use SQLite. Its quick to manage. Believe me, with just 1 Hr of playing with SQLite, you’d want to use it in production as well!
* Even in production, if it is small application with less traffic expected, go ahead with SQLite. e.g your blog.

SQLite is a so cool choice for such tasks, that python > 2.5 choosen it and comes with inbuilt SQLite 3 package. So nothing to install. :-)
(Please note in this entire post, I am talking about SQLite3 only)

So lets get our hands dirty with SQLite.
Using distros evolved after end 2008? Most likely SQLite is already there on your system..

$ sqlite3 /tmp/mydb.db
SQLite version 3.6.10
Enter “.help” for instructions
Enter SQL statements terminated with a “;”
sqlite>

Cool na? Now you’d never want to install > 50MB MySQL. ;-)
(Even if it isn’t there, use your distros package manager to get it, its less than an MB)

Note-able facts here are, sqlite internal commands(non SQL queries) starts with a dot(.) and DOES NOT require semi-colon(;) to end.
All SQL queries will require ; (as default) to be terminated with.

e.g
sqlite> .help
sqlite> .tables

Next thing you’d want to know quickly is, SQLite operates on single database by default.
Command sqlite3 expects a database name to be passed as parameter, if the file exists, it will be used as single database file for everything, else it will be created. So no more hiccups on DB migration, just carry this file :)

If you are a user of MySQL database, few replacements are..
show tables; => .tables
show databases; => .databases
mysqldump => .dump
describe table; => .schema

(I haven’t noticed any change in queries, they may exist, please consult the manual)

Next comes a small session with MySQL to SQLite:
In this exercise I am migrating a present database on MySQL to SQLite, and then do some pricks with it..

$ mysqldump –compact –no-create-db –no-data anxa | grep -v ^SET | sed s/\ ENGINE\=MyISAM\ DEFAULT\ CHARSET\=latin1//
This will give me queries to create tables. Lets pipe this output to create our DB.

$ mysqldump –compact –no-create-db –no-data anxa | grep -v ^SET | sed s/\ ENGINE\=MyISAM\ DEFAULT\ CHARSET\=latin1// | sqlite3 /tmp/anxa.sqlite

Created! :-)

Now fire the prompt of sqlite…

$ sqlite3 /tmp/anxa.sqlite
SQLite version 3.6.10
Enter “.help” for instructions
Enter SQL statements terminated with a “;”

sqlite> .tables
addr fff new smsstore test

sqlite> .schema addr
CREATE TABLE `addr` (
`nick` varchar(20) NOT NULL,
`name` varchar(20) default NULL,
`nummer` varchar(12) default NULL,
`email` varchar(40) default NULL,
PRIMARY KEY (`nick`)
);
sqlite> insert into addr values ( ‘nick’, ‘Name’, ‘9999999999′, ‘id@user.domin’ );
sqlite> select * from addr;
nick|Name|9999999999|id@user.domin

Indeed output is not as cool as MySQL. Then just switch the mode… .mode
Bet you don’t have this one in MySQL. :-)

Do you also know, SQLite has wrappers for Rails Migrations, Python SQLObject, Django framework, PHP native support, PHP ADODB and lots more.
So you can actually use SQLite without rewriting a single line of code, if your application is powered by some wrapper.

That’s all for SQLite. Enjoy…

Post to Twitter Tweet This Post

Quickly sort with Quicksort…

7 Nov 2009 In: Algorithm, Programming

This post is regarding quicksort…

In quicksort algo, we choose a pivot element and then brings all the smaller elements to the left of the list and biggers one on the right…
Then we go on processing the same with left and right sub list dividing the original list by the pivot element.

In each pass the pivot acquires its correct position.

This yields us the sorted list in the end.

Its best case and average case complexity is nlog(n) and worst case to be (n square), where the list is already sorted or pivot is unique maximum or minimum.

It is not in-place and is not a stable sort…

An implementation in C++ is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * Quick sort algorithm implementation.
 * Best case: nlog(n)
 * Average case: nlog(n)
 * Worst case: n square.
 */
 
#include <iostream>
#include <cstdio>
#include <cstdlib>
 
#include <stdarg.h>          /* For variable number of arguments */
 
#define MAXLISTSIZE 100      /* Can sort upto MAXLISTSIZE elements */
 
using namespace::std;
 
/*
 * Quicksort implemented as a class..
 */
class Quicksort {
   private:
      int quickList[MAXLISTSIZE];                              /* Our quick list of elements */
      int quickCounter;                                        /* Our counter for this list */
      int quickSort ( int sortingList[], int start, int end ); /* Performs quick sort algorithm */
   public:
      Quicksort ();                                            /* Our constructor function */
      int performQuickSort ();                                 /* Calls quick sort algo from outside */
      int addElement ( int numOfElements, ... );               /* Adds n elements to our quick list to sort */
};
 
/*
 * Consrtuctor definiton..
 */
Quicksort::Quicksort () {
   quickCounter = 0;
}
 
/*
 * Adds numOfElements in the quick list to be sorted.
 */
int Quicksort::addElement ( int numOfElements, ... ) {
   va_list numbers;
   va_start ( numbers, numOfElements );
   cout << "Adding: " << endl;
   for ( int i = 0 ; i < numOfElements ; i++ ) {
      quickList[quickCounter++] = va_arg ( numbers, int );
      cout << quickList[quickCounter-1] << "\t";
   }
   cout << endl;
   return EXIT_SUCCESS;
}
 
/*
 * Performs quick sort algo as recurcive function..
 * Learn more: http://en.wikipedia.org/wiki/Quicksort
 */
int Quicksort::quickSort ( int sortingList[], int start, int end ) {
   if ( (end - start) <= 1 ) {
      return 0;
   }
   int pivotIdx = (end+start) / 2;
   int lessCtr = 0; int moreCtr = MAXLISTSIZE+2;
   int tempList[(MAXLISTSIZE*2)+1];
   for ( int i = 0 ; i < MAXLISTSIZE*2 ; i++ ) {
      tempList[i] = 0;
   }
   tempList[MAXLISTSIZE+1] = sortingList[pivotIdx];
   for ( int i = start ; i < end ; i++ ) {
      if ( sortingList[i] < sortingList[pivotIdx] ) {
         tempList[lessCtr++] = sortingList[i];
      }
      else if ( sortingList[i] > sortingList[pivotIdx] ) {
         tempList[moreCtr++] = sortingList[i];
      }
   }
   int j = start;
   for ( int i = 0 ; i < MAXLISTSIZE*2 ; i++ ) {
      if ( tempList[i] != 0 ) {
         sortingList[j++] = tempList[i];
      }
   }
   quickSort ( quickList, 0, pivotIdx );
   quickSort ( quickList, pivotIdx+1, end );
   return EXIT_SUCCESS;
}
 
/*
 * Caller function for quicksort..
 */
int Quicksort::performQuickSort () {
   cout << "Quick sorting..." << endl;
   quickSort ( quickList, 0, quickCounter );
   for ( int i = 0 ; i < quickCounter ; i++ ) {
      cout << quickList[i] << "\t";
   }
   cout << endl;
}
 
/*
 * Test case..
 */
int main () {
   Quicksort qs;
   /* Sorting 11 elements as specified after argument 1.. */
   qs.addElement ( 11, 2, 4, 3, 7, 11, 9, 13, 8, 20, 15, 5 );
   qs.performQuickSort ();    /* Do quicksort.. */
   return 0;
}

Sample run:
[shamail@macintosh Quicksort/]$ ./a.out
Adding:
2 4 3 7 11 9 13 8 20 15 5
Quick sorting…
2 3 4 5 7 8 9 11 13 15 20

:-) Read more at: http://en.wikipedia.org/wiki/Quicksort

Post to Twitter Tweet This Post

So, me again with code! This time its BST…

Binary Search Tree is a tree with the following properties:

  • Since its a kind of binary tree, hence every node can have either a left child, or right child.
  • Insertion is done as, if the element to be inserted is greater than the present node descend to right, else left. Insert where there is no/null node.
  • Deletion: To delete a node, reach till the node(N), find the inorder successor of this node(R), replace the value of R with N now delete R.
  • (Inode successor is the leftmost subchild or right sub tree)

Code to implement BST in C++ is as follows… (with bst.cc as source file, and bst.h as header file)

searchtree.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Binary Search Tree
 */
 
#include <iostream>
#include <cstdio>
#include <cstdlib>
 
/*
 * Nodal definition of our BST
 */
struct Node {
   int dataElement;
   Node *parent;           /* Keeping pointer to parent node! Easier in deletion */
   Node *left, *right;     /* Left and right subtree of a node */
};
 
/*
 * Binary Tree implemented via class
 */
class BinarySearchTree {
   private:
      Node *start;                        /* Our start of the Tree */
      int doinorder ( Node *node );       /* Recursive funtion to to inorder */
      Node *makeNode ( int data, Node *parent );      /* Bring one Node from the memory */
      Node *inorderSuccessor ( Node *p ); /* Finds the inorder successor of a node */
   public:
      BinarySearchTree ();                            /* Constructor function */
      int insert ( int data );                        /* Insert a node in a BST at proper position */
      int inorder ();                                 /* Calls doinorder with initial node, or start */
      int idelete ( int value );                      /* Delete a node from BST */
};

bst.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* 
 * Binary Search Tree Implementation
 */
 
#include "searchtree.h"
 
using namespace::std;
 
/*
 * Our Constructor definition
 */
BinarySearchTree::BinarySearchTree () {
}
 
/*
 * Make a node..
 */
Node *BinarySearchTree::makeNode ( int data, Node *parent ) {
   Node *tmp = (Node *) malloc ( sizeof (Node) );
   tmp->dataElement = data;
   tmp->parent = parent;
   return tmp;
}
 
int BinarySearchTree::insert ( int data ) {
   cout << "Going to insert... " << data << endl;
   if ( start == NULL ) {
      start = makeNode (data, NULL);
   }
   else {
      Node *iter = start;
      while ( 1 ) {
         if ( data < iter->dataElement ) {      /* Probe left... */
            if ( iter->left == NULL ) {
               iter->left = makeNode ( data, iter );
               break;
            }
            else 
               iter = iter->left;
         }
         else {                                 /* Probe right... */
            if ( iter->right == NULL ) {
               iter->right = makeNode ( data, iter );
               break;
            }
            else 
               iter = iter->right;
         }
      }
   }
}
 
/*
 * Recursive internal function for performing inorder traversal.
 */
int BinarySearchTree::doinorder ( Node *node ) {
   if ( node == NULL )
      return EXIT_SUCCESS;
   doinorder ( node->left );
   cout << node->dataElement << "\t";
   doinorder ( node->right );
   return EXIT_SUCCESS;
}
 
/*
 * Public member to perform inorder traversal on the BST.
 */
int BinarySearchTree::inorder () {
   Node *iter = start;
   doinorder ( start );
}
 
/*
 * Finds its in order successor.
 */
Node *BinarySearchTree::inorderSuccessor ( Node *p ) {
   /* Its the leftmost child of right subtree */
   Node *trav = p;
   if ( trav->right == NULL ) {
      return trav;
   }
   trav = trav->right;
   while ( trav->left != NULL ) {
      trav = trav->left;
   }
   return trav;
}
 
/*
 * Deletion for BST.
 * Algorithm:
 *    If leaf = Go ahead, remove it as such.
 *    If one child = Delete and replace it with its child.
 *    Else = To be deleted = N, Inorder sucessor = R, replace value of N with value of R, delete R.
 */
int BinarySearchTree::idelete ( int value ) {
   /* 1. Reach till the node */
   Node *iter = start;
   Node *toDel = NULL;
   if ( iter == NULL ) {
      cerr << "Empty BST..." << endl;
      return EXIT_FAILURE;
   }
   while ( 1 ) {
      if ( iter->dataElement == value ) {
         toDel = iter;
         break;
      }
      else {
         if ( value < iter->dataElement ) {
            if ( iter->left == NULL ) 
               break;
            iter = iter->left;
         }
         else {
            if ( iter->right== NULL ) 
               break;
            iter = iter->right;
         }
      }
   }
   if ( toDel == NULL ) {
      cout << "No such node to delete... Aborting!" << endl;
      return EXIT_FAILURE;
   }
   else {
      cout << "Deleting node with value.. " << toDel->dataElement << endl;
   }
   /* CASE 1. Has no left or right child. Delete straight away.. */
   if ( toDel->left == NULL && toDel->right == NULL ) {
      Node *parent = toDel->parent;
      if ( parent == NULL ) { /* Means root node */
         toDel = NULL;
         free ( toDel );
      }
      else {
         if ( parent -> left == toDel )
            parent -> left = NULL;
         else
            parent -> right = NULL;
      }
      free ( toDel );
   }
 
   /* CASE 2.1 Has left child only */
   if ( toDel->left != NULL && toDel->right == NULL ) {
      Node *parent = toDel->parent;
      Node *place = toDel->left;
      if ( parent -> left == toDel )
         parent -> left = place;
      else
         parent -> right = place;
      free (toDel);
   }
   /* CASE 2.2 Has right child only */
   if ( toDel->left == NULL && toDel->right != NULL ) {
      Node *parent = toDel->parent;
      Node *place = toDel->right;
      if ( parent -> left == toDel )
         parent -> left = place;
      else
         parent -> right = place;
      free (toDel);
   }
   /* CASE 3. Both its left and right are preoccupied.
    * Convention: Following inorder successor..
    */
   if ( toDel->left != NULL && toDel->right != NULL ) {
      Node *iSuccessor = inorderSuccessor ( toDel );
      toDel->dataElement = iSuccessor->dataElement;
      if ( iSuccessor->parent->left == iSuccessor ) {
         iSuccessor->parent->left = NULL;
      }
      else {
         iSuccessor->parent->right = NULL;
      }
      free (iSuccessor);
   }
   return EXIT_SUCCESS;
}
 
/*
 * Test case
 */
int main () {
   BinarySearchTree mybst;
   mybst.insert ( 8 );
   mybst.insert ( 4 );
   mybst.insert ( 2 );
   mybst.insert ( 5 );
   mybst.insert ( 7 );
   mybst.insert ( 3 );
   mybst.insert ( 1 );
   cout << "Traversing..." << endl;
   mybst.inorder ();
   cout << "\n";
   mybst.idelete ( 4 );
   mybst.inorder ();
   cout << "\n";
   mybst.idelete ( 2 );
   mybst.inorder ();
   cout << "\n";
   return (0);
}

That all for BST :-)
Reference: http://en.wikipedia.org/wiki/Binary_search_tree

Sample output:
Going to insert… 8
Going to insert… 4
Going to insert… 2
Going to insert… 5
Going to insert… 7
Going to insert… 3
Going to insert… 1
Traversing…
1 2 3 4 5 7 8
Deleting node with value.. 4
1 2 3 5 8
Deleting node with value.. 2
1 3 5 8

Post to Twitter Tweet This Post

METRO: Condition deteriorating!

30 Oct 2009 In: Metro

I have been a daily traveller of the Delhi Metro from about 5 months (Since June 09). As the days are passing by, I’ve noticed the problems in the service that are creeping in to the system. And to the worst, they ain’t being taken care of!

1. Metro rails now run at irregular frequency. Initially, I used to get a metro rail every 4 minutes, but now, missing a train means, you may get the next train in 2 mins or 10 mins, it all depends on your luck. (or if you are carrying some brilliant luck you’ll see next metro arriving with the previous one is still clearly visibly on the track).
2. Unconditional delays, Since the day metro derailed near Dwarka (August 12th) the service is encountering unconditional delays.
Every next day you may hear an announcement, “Is yatra main thoda vilambh hoga, khed hai” (There will be short delay to this service, we apologise for the inconvenience).
3. Rush! About few months back, I used to get a seat (both ways), or at-least after a couple of stations or so. But now, I have to bear 35 mins journey each way standing like dumbs. And to this, DMRC is paying no attention.. Can’t they add 2 extra coaches to the trains. I believe if you can have such costly tracks already up, coaches will not be a hindrance as per the cost is concerned, keeping in mind the revenue generated by the project. Probably, this is true India. Make it and forget! Who cares what the insight situation is. And to add to it, they are about to rise the fare.

A quote in urdu say: “Qabar ka haal to murda he jane” (Its the dead who knows what graveyad looks like)

4. Technical faults, I’ve noticed that announcements are never true at most of the stations (not all). At Indraprastha station, on platform 2 (towards Dwarka) The announcement is made when almost 7-8mins are remaining for the train to arrive, “Train with it destination to Dwarka…“. At this moment, the metro clock shows that its 1 minute remaining. At the very moment, the clock on the other platform says about 6-7 minutes remaining for the train towards Yamuna Bank (Platform 1).
To your surprise, the train towards Yamuna Bank arrives, at proper time, after 6-7 mins. And the other clock is still on 1 minute for Dwarka side! The Yamuna bank train takes the stop, move out and disappears. Then later after another couple of minutes comes the train for Dwarka! Whats this crap? If the train is supposed to come after 8-9 minutes why the clock at the station sounds like tuned by dumb engineers? Why false announcement?

Also, almost every couple of days, I see, its poor driver who has to announce which station is this, as the automatic announcement system has faced a set back.
5. Station design, Almost all of the stations, except Rajiv Chowk, as far as I consider, are not ergonomics in terms of Escalators! If you want to take the escalator, come take a a big round (even more than the cost to state to climb the stairs) and find the escalators.

If the condition will persist at-least they will lose one person to stop using Metro and travel by my own conveyance. That’s all from my side for DMRC.

Post to Twitter Tweet This Post

I Don’t pirate anymore!

22 Oct 2009 In: Piracy

From few months I am noticing that I no more pirate.

Was I pirating earlier?
Technically speaking, yes!

Let me explain, piracy is just not confined to copying the original disc of MS Windows(r) from a friend, rather its very broad term.

So where all are we pirating stuff?

1. The softwares, like antivirus, word processor and 10s of them, are all purchased from an authorized source?
2. Are you a frequent downloader of Music? Where is that you are downloading from?
3. Love movies as well? If the last movie you watched was downloaded from some premium sharing sites (like rapidshare) or community driven torrent?
4. Did you just got a shareware software that you are liking a lot and using? — Well how can this be piracy? I’ll explain.
5. So you are downloading a simple video file of some marriage ceremony(self composed), of few GBs and the friend shared it via rapidshare. Now after few 100s of MB download it says “wait for x many minutes/hours to continue downloading” (as you have a free account). Are you sure you did not restarted your router and cleared the cookies? Did not used any 3rd party proxy server? Waited that many minutes/hours for rapidshare to permit you the download again?
6. Are you a developer? Did you never used any code that has a license of GPL(say) in your propriety code?
7. Oh! the new cool Google wave. Managed to get an invite and accessing from outside USA?
8. Are you using Skype to make calls to PSTN in India?
9. Oh whats that wallpaper on your desktop? Is that downloaded from some random google search, have you seen the terms of that web site if it is allowing to use their contents?
10. Lastly the very basic, have you ever installed copied version of MS Windows(r) (any X) ?

This all leads to piracy++.

Lets get to know each of them in categories and see how to legally acquire them in a cost effective way.

Softwares:
The most basic form of piracy is “software piracy”. Go to a market like “Nehru Place” and fill yourselves with the pleasing sound of…
Aaeye madam, software antivirus CD game… Sir software CD game. Bista Bard GTA norton.. Aaeye aeye
This is real piracy. 1000s of developers are working day and night to make so rock solid and stable softwares and those guys in minutes are copying them, just like that.
Measure: Nothing. Its India. Its like 1000 people make it and 1000000 people live on it by pirating them.

Point here is, how we as educated people are pirating?
In short, by purchasing them. For us that “software antivirus CD game” is not the only source to get pirated contents. Daily we are using sites like rapidshare, torrentz etc to get those out there. And they are professionally cracked, comes with a great documentation to apply crack(sometimes even better than the softwares documentation itself), hence they don’t hitch when you run them.

LESSON: Do not aid piracy. There are 100s of emerging companies that have brilliant software ideas and wants to come up, this piracy doesn’t hit big companies a lot, but to small companies, its the worst.

Music:
Second biggest thing that we would found being pirated is Music. Practically, music is a thing that is seldom acquired legally. And 99% times it is downloaded or purchased as a pack of 15 MP3 movies in one CD.
Music piracy is easier as well, because of the size constrains. Songs of one complete movie are seldom more than 100MB. From rapidshare you can acquire it in a one go, on the very next day of movie release.

Measure: Please use stores like iTunes, T-Series, or the Albums official web page. They do charge a nominal rates for the songs, but are definitely worth.

The point here is, actually its only the producer of the album is hit, but  later accounts to you only. How? If the producer will not be able to earn from album then the show ticket will be 150/- instead of 90/-

Movies:
This is where no one compromises, everyone wants better quality and sound. Downloading from torrent is a pain. So better get it on rent for just Rs 10 or 20. And do not aid to piracy. It will give you better quality better sound and more enjoyment.
Please note: Rental is 100% legal way to watch movie, but a rented movie is not meant to be dumped on disc and the service provider must be genuine, and not the one who sits at the “nukkadwala shop” with a copy disc in hand for you.
Now for new movies, if you want to wipe out all the entertainment and fun, cool graphics and animation, want to listen to highly echoing sound and you are watching movie just for the sake of knowing the story! Go ahead and acquire dubbed movie, available at “nukkadwala shop” near you…

Internet:
Do you know, even a desktop wallpaper, if not allowed in the terms and conditions of the web site from where you acquired it, aids to its piracy.
Almost you’ll find every book on google books to read, liked a chapter? Do not take a screenshot and OCR it. Better write it…
Earlier i gave an example of shareware software.
Shareware and demo softwares are 100% legal to install and use, but ONLY for evaluation. Doing business with them and using them for productivity is 100% illegal. Almost all the companies around the world DOES NOT permit the use of sharewares on the office systems. Reason is same.

A lot said, but if we sum up the amounts that we have to spend to get them all legally, probably this will cross the salaries?
Yes! Indeed they will.
So there are the ways.

How?

For softwares, minimize the use of costly softwares.
e.g If you have to use MS office sometime to draft homely documents, it is not advisable to invest 19,990/- to purchase it. Rely on free alternative like OpenOffice.org. But if that you have regular DTP work, you are getting paid to use that.. go ahead.
Get Windows for 25,000? Thats more than the hardware!
Presumably you should. Thats a one time investment, and you should insist on original windows. Apart from technical support and updates, you also enjoy peace of mind. But if you are an enthusiast or student.. go explore GNU/Linux Solaris, install Darwin on you PC, hack BSD!
For professional softwares like Adobe Creative Suite, Autodesk’s Autocad, Revit etc… Its only that you are professionally bound, hence using it. Purchase it. If you are a student ask for you college/school. They will provide you for sure, its there duty to do so. Infact many softwares, e.g Autodesks products like Archicad, certain Adobe products, Red Hat etc to name a few, provide free educational license. Use them.

In a nutshell, DO NOT install 143 softwares on your computer, all pirated, rather install 2, that you actually use.

For music, listen online. (you are using broadband connection, right?). Once you liked the album, purchase it. Its usually priced @ 100/-. Thats pretty fair for a music that you liked.

For movies, go for rental. Even sites like bigflix provides home drop and pickup of rented movies. For latest blockbuster, you would like to go to a cinema near you?

For other sharewares etc, test them thoroughly, before actually purchasing them, thats what shareware is meant for. And then go for it.
I’ll recommend to check out open source alternatives before you go for them. They are most of the times very powerful and fits the needs.
Try other OSS operating system like Ubuntu etc, if you want some cool cost saving.

Lastly the title of the post is, why I don’t pirate?

Reason: Since now I’ve moved from student to professional life, I can think on what is that I actually want, and then can afford it. I don’t pirate movies anymore, probably music I do, that also I am minimizing. For softwares, I completely rely on OSS softwares and tools. Apart from that, I did purchased OS X and use that.

As a conclusion, its just DO NOT flood yourself with things, be selective and stay legal.

Post to Twitter Tweet This Post

TRIE, a C++ approach…

9 Oct 2009 In: Programming, linux

I was just wondering that if I still remember some data structures that I learnt in college! (Have to appear in an interview sooner) For that I wrote up in quick a trie implementation. And now I think “yes!” I remember! :)

The code is as follows [download]…

/* trie.cc - short and sweet data storage API :-)
 * Implementation of TRIE data structure, a bare bone.
 * Fri Oct  9 22:49:25 IST 2009
 * Author: Shamail Tayyab [me@shamail.in]
 * Creative Commons BY-NC-ND.
 * Insertion: O(n). Searching: O(n).
 */
 
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
 
#define MAXDICTELEMENTS 27          /* Using a-z and space */
#define MAXDEPTH 20                 /* Supporting 20 character depth of dictionary */
 
using namespace::std;
 
/* Our dictionary node */
struct Node {
   int wordEnd;   /* Represents that a word is ending here also */
   Node *next[MAXDICTELEMENTS];
};
 
/* Trie represented as class */
class Trie {
   private:
      Node *start;                  /* Our start pointer */
      char dict[MAXDICTELEMENTS];   /* Our char dictionary or supported characters in TRIE */
      Node *createNode ();                /* Create and mallocs a node */
      int printThisNode ( Node * );       /* Debugging function */
      int isEmpty ( Node *, char );       /* Detects if we have an empty node at given depth */
      int getIndexForChar ( char );       /* Returns ith position from dict array */
   public:
      Trie ();                            /* Constructor function to initialize the TRIE */
      ~Trie ();                           /* FREEing up of memory. FIXME required */
      int insert ( char * );              /* Insert a word in TRIE */
      void reportSearch ( char *word );   /* Searches and reports on stderr the result in printed form */
      int search ( char *word );          /* API to search */
};
 
Trie::Trie () {
   start = (Node *)malloc ( sizeof ( Node ) );
   strcpy ( dict, "abcdefghijklmnopqrstuvwxyz " );    /* Add here for any other word list, also update MAXDICTELEMENTS*/
}
 
Trie::~Trie () {
   free (start);
}
 
/*
 * Array index for TRIE's next.
 */
int Trie::getIndexForChar ( char c ) {
   for ( int i = 0 ; i < MAXDICTELEMENTS ; i++ ) {
      if ( dict[i] == c ) {
         return i;
      }
   }
   return ( -1 );
}
 
/*
 * For debugging, prints which all nodes are free in a given level of TRIE.
 */
int Trie::printThisNode ( Node * treeNode ) {
   if ( treeNode == NULL ) {
      return EXIT_FAILURE;
   }
   for ( int i = 0 ; i < MAXDICTELEMENTS ; i++ ) {
      if ( treeNode -> next[i] == NULL ) {
         cout << "Empty(" << i << ")\t";
      }
      else {
         cout << "Filled(" << i << ")\t";
      }
      cout << endl;
   }
}
 
/*
 * If the TRIE has an empty node at this treeNode at cth position?
 */
int Trie::isEmpty ( Node *treeNode, char ch ) {
   if ( treeNode -> next[getIndexForChar(ch)] == NULL )
      return (1);
   else
      return (0);
}
 
/*
 * Brings one node from the memory.
 */
Node *Trie::createNode () {
   Node *created = (Node *) malloc ( sizeof ( Node ) );
   created -> wordEnd = 0;
   return (created);
}
 
/*
 * Insert a word into the TRIE.
 * Quick Algo: Traverse to the right depth, insert.. O(n).
 */
int Trie::insert ( char *word ) {
   if ( strlen ( word ) > MAXDEPTH ) {
      cerr << "MAXDEPTH Exceeded! Cannot insert(" << word << ")" << endl;
      return EXIT_FAILURE;
   }
   cerr << "Adding word " << word << " to the dictionary..." << endl;
   Node *operatingOn = start;
   for ( int i = 0 ; i < strlen ( word ) ; i++ ) {
      if ( isEmpty ( operatingOn, word[i] ) ) {
         Node *childHere = createNode ();
         operatingOn -> next[getIndexForChar(word[i])] = childHere;
         operatingOn = childHere;
      }
   }
   operatingOn -> wordEnd = 1;
   return EXIT_SUCCESS;
}
 
/* Searches in a TRIE the given word.
 * Quick Algo: Iterate on chars, if the pointer is null anywhere, its not found. else accent into one level on this character.
 *             If even all pointers are fixed and last pointer has 0 in its wordEnd, still not found.
 *             Else found.
 */
int Trie::search ( char *word ) {
   Node *iterator = start;
   if ( iterator == NULL )
      return (EXIT_FAILURE);
   if ( strlen ( word ) > MAXDEPTH ) {
      cerr << "MAXDEPTH Exceeded!" << endl;
      return (EXIT_FAILURE);
   }
   for ( int i = 0 ; i < strlen(word) ; i++ ) {
      if ( iterator -> next[getIndexForChar(word[i])] == NULL )
         return EXIT_FAILURE;
      iterator = iterator -> next[getIndexForChar(word[i])];
   }
   if ( iterator -> wordEnd == 0 ) {
      return EXIT_FAILURE;
   }
   else {
      return EXIT_SUCCESS;
   }
 
}
 
/*
 * Perform search and print result on STDERR.
 */
void Trie::reportSearch ( char *word ) {
   if ( search ( word ) ) {
      cerr << "Not Found!" << endl;
   }
   else 
      cerr << "Found!" << endl;
}
 
/* 
 * Test case 
 */
int main ( int argc, char *argv[] ) {
   Trie t;
   t.insert ( (char *)"shamail" );
   t.insert ( (char *)"altec lansing" );
   t.insert ( (char *)"altec lansing is my speaker brand" );
   t.reportSearch ( (char *)"shamail" );
   t.reportSearch ( (char *)"badceb" );
   t.reportSearch ( (char *)"alt" );
   t.reportSearch ( (char *)"altec lansin" );
   t.reportSearch ( (char *)"altec lansing" );
   return 0;
}

Sample run:
shamail@busybox:~$ ./trie
Adding word shamail to the dictionary…
Adding word altec lansing to the dictionary…
MAXDEPTH Exceeded! Cannot insert(altec lansing is my speaker brand)
Found!
Not Found!
Not Found!
Not Found!
Found!

Enjoy :)

Post to Twitter Tweet This Post

Tarana – Jamia Millia Islamia

7 Oct 2009 In: College

This post is my dedication to my college Jamia, which I miss a lot now…

Audio: Format: MP3 @ 64Kbps [download].

Dayar-e-shauq mera, Dayar-e-shauq mera

Shehr-e-aarzoo mera, Shehr-e-aarzoo mera

Hue the aake yahin khemazan woh deewaney
Uthhe the sun ke jo aawaz-e-rehbaraan-e-watan
Yaheen se shauq ki be rabtiyon ko rabt mila
Isi ne hosh ko bakhsha junoon ka pairahan
Yahin se lala-e-sehra ko ye suraagh mila
Ke dil ke daagh ko kis tarha rakhte hein roshan

Dayar-e-shauq mera, Shehr-e-aarzoo mera

Ye ehle shauq ki basti, ye sarphiron ka dayar
Yahan ki subha nirali, yahan ki shaam nayi
Yahan ki rasm-o-rah hai kashi juda sab se
Yahan ke jam naye tarha, raqs rasm-e-jam nayi
Yahan pe tashna labi maikashi ka haasil hai
Ye bazm-e-dil hai yahan ki sala-e-aam nai

Dayar-e-shauq mera, Shehr-e-aarzoo mera

Yahan pe shamma-e-hidayat hai sirf apna zamir
Yahan pe qibla-e-iman kaba-e-dil hai
Safar hai deen yahan kufr hai qayaam yahan
Yahan pe raah rooi khud husul-e-manzil hai
Shanaawari ka taqaza hai nau-ba-nau toofaan
Kinar-e-mauj mein aasoodgi-e-saahil hai

Urdu version:

http://shamail.in/tarana.jpg

Translation:

by Prof. M. Zakir

This is the land of my hopes
This is the land of my dreams

This is where men with zeal stayed
Men who answered the leaders’ call
It is here that torn-off love
Found the cohesive chords
It is here that wayward passions
Formed into frenzied love
It is here that the wild tulip learnt
How to make the scar of heart aglow

This is the land of my hopes
This is the land of my dreams

This is the place of men of vision
And of those with a challenging thought
Every morning here is new
And every evening newer still
Different is this tavern
And different are its norms
Different are the dancing cups
And different is their dance
Here drinking begets thirst anew
And different is this tavern’s call

This is the land of my hopes
This is the land of my dreams

Here, conscience is the beacon light
And conscience is the guide
Here is the Mecca of heart resides the guiding faith
Ceaseless movement is our faith
And blasphemy it is to stay still
Here, the destined goal is the march on and on
Here, the swimming urge seeks
Newer and newer storms
Restless wave itself is our resurrected shore

Post to Twitter Tweet This Post

In this article I am going to discuss about CGI, what why and how and then how can scaling be done when using CGI. The article will primarily focus C and python as the programming language, but this can be used with almost any of the language.

So, lets begin with very basic thing, what CGI is?
CGI, or common gateway interface is a method or protocol by which a user requests the server(web server) for some contents, for which the CGI runs a script or program and the output of the program(HTML in case of web) is sent back to the user.
An example of CGI program can be a wiki, for which the user requests page X(browser does it for the user), webserver calls up a program to fetch the page, and then converts it to HTML and sends this to user, and using the web browser the user can see the page.

So thats simple, in general..

web look of cgi system

Now, lets come to implementation part…
The CGI protocol says.. Whatever request will come to me, I’ll create an environment(1) for that, run the specified program in that environment, now you(programmer) should give me the output(2) that I’ll send back to the user.

Before going to the explanation, lets get to know what a CGI program is?
A CGI program is a normal program/script in any language that is executable (mode x) and should return an output of this format… (this discussion is maily for web, so for that..)

Header1: Field value
Header2: Field value

HTML/Body

So, code a program in any language, that outputs, from line 0 HTTP headers(\n seperated), the headers are considered till CGI encounters \n\n. From this contents follows, which can be anything like html. Make this executable and place it in CGI directory of the webserver.. its now a web program.

1) So, what is environment?
Environmet is a nothing but a plain invocation of the CGI program with few environment variables set. So, an environment variable like HTTP_HOST etc will be pre set to its appropriate values. These can be retrieved using getenv function in most of the programing languages.
2) What is output?
It can be HTML, binary etc depending on the request.

EXAMPLE:
So having seen that, lets create a basic hello world cgi script. Lets assume you have your webserver running with /var/www/cgi-bin as you CGI directory. Also you have C compiler and python  installed. Also do remember, CGI is server side only, so we can use any language that we want.
Make a file, say hello.c anywhere(its a good idea to organise you code and executables seperately), with these contents.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main () {
   /* Printing headers... */
   printf ( "Content-type: text/html\n" );   /* \n ensures we sent the header */
   printf ( "\n" );                          /* \n in a blank line marks end of headers */
 
   /* Printing contents... */
   printf ( "<html> <head> <title> Hello </title> </head> <body> <h2> Hello World.. </h2> </body> </html>" );
   printf ( "\n" );                          /* Marks the end of the contents as well */
   return (0);    /* Program must terminate correctly so that CGI will know, there is no Internal server error */
}

Now compile this program as:
$ gcc hello.c -o /var/www/cgi-bin/hello

Same thing with python, make directly a file called hello in /var/www/cgi-bin/ with these contents

1
2
3
4
5
6
#! /usr/bin/env python
 
print "Content-type: text/html"
print
 
print "<html> <head> <title> Hello </title> </head> <body> <h2> Hello World.. </h2> </body> </html>"

This will make an target file in our CGI directory, and executable also, if it is in python or some other language or a script, then manually do
$ chmod +x /var/www/cgi-bin/hello

Now point your browser to http://localhost/cgi-bin/hello and see the CGI program running for web server.

web look of cgi program

Now that was simple? Isn’t it? But is that sufficient to make huge site? Certainly not… So now what is it that CGI still rocks?

CGI is server side technology, that empowers you to develop web apps the way you like. This means, if I am a python guy, I can very well make one in it. And we DO NOT need anything in addition that server supports CGI scripts execution (Almost all of the servers including Apache, IIS and lighthttpd supports this). For performance we certainly consider other modules and stuff, but thats a later case.

So one can argue, this will become very difficult to develop and write bare HTML!! Who says? Plug in a library in your programming language that enables you to bring the contents you printed from a template file! Whats say “kid” for python? “rhtml” for ruby? And if not, even a simple sed will do the trick! Similarly plug your favourite ORM and map SQL with objects and there you go like MVC!

Now lets come to the speed issues. CGI is known to invoke a program for each request that it makes, so this will make a havoc with high load web server?
No.. the basic CGI can be used for development, but prefer mods of the language you are using.. e.g mod_python can make it rapidly fast as compared to basic CGI.
Apart from that, there is a FastCGI module, very popular, that make a persistent environment, that means it will not re invoke whole executable script again, e.g in case of python, the interpreter is already in the memory, and FastCGI will internally maps the requests and the output. So makes it drastically fast.
Also, the CGI gives you the fastest of all the times, write your program in C/C++, being native program and not an interpreted script, this will be many folds faster.

SCALING:
Having discussed all that, lets now focus on scaling. Imagine a situation, where we are developing a web site, in CGI and python with MySQL backend, puts it in Beta, and our hits grows in millions in a couple of days, what to do then?

Well, CGI scores here… Since the architecture of CGI is transparent it can be easily made to be run on distributed system. Put up apache or other web server to map the requests on specific load range to a server on the distributed network and put up the database on completely different server(can internally be distributed again), Now the individual servers are running the same code and acting along with same database, to developer it will still look like a single system.
If you want to score on the code, start converting the scripts to C/C++ programs, this will help handling almost 3-4 times higher load (in general) on same machine.

Later I’ll describe a how-to of this here only.

DOs and DONTs
- Never chmod +x any program in CGI directory that is not meant to be called from outside, including external libraries etc.
- Prefer not to allow SymLinks in the Web Servers configuration.
- Do seperate code and executables if it is to be compiled.
- Prefer static content to be served by WebServer and not by the script with Content-type: application/octet-stream unless some specific is to be done.
- Test programs for case of failure properly, and catch exceptions. This can be done on command line and writing test cases.
- Do not, rather never call scripts whos name is to be passed as web parameter. In extreme condtions, if it has to.. then perform a very strict check on the exe being called

Post to Twitter Tweet This Post

About this blog

This blog is for my publications related mostly to GNU/Linux, Web development and Python. Check out RSS feeds and stay updated.