/* Ajith - Syntax Higlighter - End ----------------------------------------------- */

7.07.2010

Implementation of Stack using Singly Linked Lists

Stacks are linear data structures which means the data is stored in what looks like a line (although vertically). In simple words we can say
A stack is a last in, first out (LIFO) abstract data type and data structure.
Basic usage of stack at the Architecture level is as a means of allocating and accessing memory.


We can only perform two fundamental operations on a stack: push and pop.

The push operation adds to the top of the list, hiding any items already on the stack, or initializing the stack if it is empty. The pop operation removes an item from the top of the list, and returns this value to the caller. A pop either reveals previously concealed items, or results in an empty list.

A stack is a restricted data structure, because only a small number of operations are performed on it.

6.30.2010

strace - diagnostic, debugging and reverse engineering tool

Many times we come across hopeless situations where a program when compiled and installed in GNU/Linux just fails to run. Then we have to trace the output of the misbehaving program. But tracing the output of a program throws up a lot of data and it is a daunting task to go through volumes of data. Still there are cases where we are not fruitful in pin pointing the cause of error.

In this situation strace also known as system-call tracer comes for rescue. It is a debugging tool that monitors the system calls used by a program and all the signals it receives.

A system call is the most common way programs communicate with the kernel. System calls include reading and writing data, opening and closing files and all kinds of network communication. Under Linux, a system call is done by calling a special interrupt with the number of the system call and its parameters stored in the CPU's registers.

Using strace is quite simple. There are two ways to let strace monitor a program.


Method 1:

To start strace along with a program, just run the executable with strace as shown below.
strace program-name
For example let us trace ls command.
$ strace ls
execve("/bin/ls", ["ls"], [/* 39 vars */]) = 0
brk(0)                                  = 0x82d4000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7787000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=76503, ...}) = 0
mmap2(NULL, 76503, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7774000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libselinux.so.1", O_RDONLY)  = 3
read(3, "177ELF111���������3�3�1���@G��004���"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=104148, ...}) = 0
mmap2(NULL, 109432, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x41d000
mmap2(0x436000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18) = 0x436000
close(3)                                = 0
.
.
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7613000
write(1, "01.c  a.outn", 1201.c  a.out
)           = 12
close(1)                                = 0
munmap(0xb7613000, 4096)                = 0
close(2)                                = 0
exit_group(0)                           = ?
In the above example we are not displaying the complete output of strace command. Even though output from strace looks very complicated, this is only due to many system calls made when loading shared libraries. However, once we have found which system calls are the important ones (mainly open, read, write and the like), the results will look fairly intuitive to us.

Method 2:

If we want to monitor a process which is currently running we can attach to the process using –p option. Thus we can even debug a daemon process.
strace –p <pid-of-the-application>
For e.g
#include <stdio.h>
#include <unistd.h>

int main()
{
   sleep(20);
   return 0;
}
We will compile the above code and run it as a background process. Then we try to monitor the program using its process id as shown below.
$ gcc main.c

$ ./a.out &
[1] 1885

$ strace -p 1885
Process 1885 attached - interrupt to quit
restart_syscall(<... resuming interrupted call ...>) = 0
exit_group(0)                           = ?
Process 1885 detached
[1]+  Done                    ./a.out
In contrast to a debugger, strace does not need a program's source code to produce human-readable output.

Some handy options

Below example is used in the discussion of other important options supported by strace.
#include <stdio.h>

int main(void)
{
  FILE *fd = NULL;

  if(fd = fopen("test","rw"))
    {   
      printf("TEST file openedn");
      fclose(fd);
    }   
  else
    {   
      printf("Failed to open the filen");
    }   

  return 0;
}

Providing the time taken by multiple system calls in a program


Using –c option strace provides summary information on executing a program.

It provides information like number of times a system call is used, time spent executing various system calls, number of times errors returned as shown below.
$ strace -c ./a.out 
Failed to open the file
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 91.47    0.004000        4000         1           execve
  8.53    0.000373         124         3         3 access
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0         3         1 open
  0.00    0.000000           0         2           close
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           mprotect
  0.00    0.000000           0         7           mmap2
  0.00    0.000000           0         3           fstat64
  0.00    0.000000           0         1           set_thread_area
------ ----------- ----------- --------- --------- ----------------
100.00    0.004373                    29         4 total

Redirecting the output to a file 


Using -o option we can redirect the complex output of strace into a file.
$ strace -o <output-file-name> <program-name>

Time spent per system call 


Using –T option we can get time spent per system call. In the below example we can see time spent per system call is printed at the end of the line.
$ strace -T ./a.out 
execve("./a.out", ["./a.out"], [/* 39 vars */]) = 0 <0.003256>
.
brk(0x9db0000)                          = 0x9db0000 <0.000123>
open("test", O_RDONLY)                  = -1 ENOENT (No such file or directory) <0.000154>
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000125>
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d4000 <0.000121>
write(1, "Failed to open the filen", 24Failed to open the file
) = 24 <0.000258>
exit_group(0)                           = ?

Prefixing time of the day for every line in trace 


It is useful sometimes to track at what time a particular is triggered. By using -t option strace will prefix each line of the trace with the time of day, which will be really helpful to find out at particular time at which call is the process blocked.
$ strace -t ./a.out 
execve("./a.out", ["./a.out"], [/* 39 vars */]) = 0 <0.003256>
.
brk(0x9db0000)                          = 0x9db0000 <0.000123>
open("test", O_RDONLY)                  = -1 ENOENT (No such file or directory) <0.000154>
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 <0.000125>
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d4000 <0.000121>
write(1, "Failed to open the filen", 24Failed to open the file
) = 24 <0.000258>
exit_group(0)                           = ?

Tracing only specific system calls 


Using –e option we can also specify which system calls to be traced. To trace only open() and close() system calls use the following command:
$ strace –e trace=’open,close’ <program-name>
Similarly we can also use negation option to not trace specific system calls. If we don’t want to trace open() system call in previous example we can give the below command
$ strace -e trace='!open,close' ./a.out
Check the man page of strace for other options.

Static Functions in C

By default all functions are implicitly declared as extern, which means they're visible across translation units. But when we use static it restricts visibility of the function to the translation unit in which it's defined. So we can say
Functions that are visible only to other functions in the same file are known as static functions.

Let use try out some code about static functions.
main.c
#include "header.h"

int main()
{
hello();
return 0;
}
func.c
#include "header.h"

void hello()
{
printf("HELLO WORLD\n");
}
header.h
#include <stdio.h>

static void hello();
If we compile above code it fails as shown below
$gcc main.c func.c
header.h:4: warning: "hello" used but never defined
/tmp/ccaHx5Ic.o: In function `main':
main.c:(.text+0x12): undefined reference to `hello'
collect2: ld returned 1 exit status
It fails in Linking since function hello() is declared as static and its definition is accessible only within func.c file but not for main.c file. All the functions within func.c can access hello() function but not by functions outside func.c file.

Using this concept we can restrict others from accessing the internal functions which we want to hide from outside world. Now we don't need to create private header files for internal functions.

Note:
For some reason, static has different meanings in in different contexts.

1. When specified on a function declaration, it makes the function local to the file.
2. When specified with a variable inside a function, it allows the variable to retain its value between calls to the function. See static variables.

It seems a little strange that the same keyword has such different meanings...

4.24.2010

Singly Linked List in C

Check Implementation of Singly Linked List for theoretical explanation regarding implementation of singly linked lists.

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

//Structure containing a Data part & a
//Link part to the next node in the List

struct Node
{
 int Data;
 struct Node *Next;
}*Head;

// Counting number of elements in the List

int length()
{
  struct Node *cur_ptr;
  int count=0;

  cur_ptr=Head;

  while(cur_ptr != NULL)
  {
     cur_ptr=cur_ptr->Next;
     count++;
  }
  return(count);
}

// Deleting a node from List depending upon the data in the node.

int delNodeData(int num)
{
  struct Node *prev_ptr, *cur_ptr;

  cur_ptr=Head;

  while(cur_ptr != NULL)
  {
     if(cur_ptr->Data == num)
     {
        if(cur_ptr==Head)
        {
           Head=cur_ptr->Next;
           free(cur_ptr);
           return 0;
        }
        else
        {
           prev_ptr->Next=cur_ptr->Next;
           free(cur_ptr);
           return 0;
        }
     }
     else
     {
        prev_ptr=cur_ptr;
        cur_ptr=cur_ptr->Next;
     }
  }

  printf("\nElement %d is not found in the List", num);
  return 1;
}

// Deleting a node from List depending upon the location in the list.

int delNodeLoc(int loc)
{
  struct Node *prev_ptr, *cur_ptr;
  int i;

  cur_ptr=Head;

  if(loc > (length()) || loc <= 0)
  {
      printf("\nDeletion of Node at given location is not possible\n ");
  }
  else
  {
      // If the location is starting of the list
      if (loc == 1)
      {
          Head=cur_ptr->Next;
          free(cur_ptr);
          return 0;
      }
      else
      {
          for(i=1;i<loc;i++)
          {
              prev_ptr=cur_ptr;
              cur_ptr=cur_ptr->Next;
          }

          prev_ptr->Next=cur_ptr->Next;
          free(cur_ptr);
      }
  }
  return 1;
}

//Adding a Node at the end of the list

void addEnd(int num)
{
  struct Node *temp1, *temp2;

  temp1=(struct Node *)malloc(sizeof(struct Node));
  temp1->Data=num;

  // Copying the Head location into another node.
  temp2=Head;

  if(Head == NULL)
  {
     // If List is empty we create First Node.
     Head=temp1;
     Head->Next=NULL;
  }
  else
  {
     // Traverse down to end of the list.
     while(temp2->Next != NULL)
     temp2=temp2->Next;

     // Append at the end of the list.
     temp1->Next=NULL;
     temp2->Next=temp1;
  }
}

// Adding a Node at the Beginning of the List

void addBeg(int num)
{
  struct Node *temp;

  temp=(struct Node *)malloc(sizeof(struct Node));
  temp->Data = num;

  if (Head == NULL)
  {
     //List is Empty
     Head=temp;
     Head->Next=NULL;
  }
  else
  {
     temp->Next=Head;
     Head=temp;
  }
}

// Adding a new Node at specified position

void addAt(int num, int loc)
{
  int i;
  struct Node *temp, *prev_ptr, *cur_ptr;

  cur_ptr=Head;

  if(loc > (length()+1) || loc <= 0)
  {
     printf("\nInsertion at given location is not possible\n ");
  }
  else
  {
      // If the location is starting of the list
      if (loc == 1)
      {
          addBeg(num);
      }
      else
      {
          for(i=1;i<loc;i++)
          {
              prev_ptr=cur_ptr;
              cur_ptr=cur_ptr->Next;
          }

          temp=(struct Node *)malloc(sizeof(struct Node));
          temp->Data=num;

          prev_ptr->Next=temp;
          temp->Next=cur_ptr;
      }
  }
}

// Displaying list contents

void display()
{
  struct Node *cur_ptr;

  cur_ptr=Head;

  if(cur_ptr==NULL)
  {
     printf("\nList is Empty");
  }
  else
  {
      printf("\nElements in the List: ");
      //traverse the entire linked list
      while(cur_ptr!=NULL)
      {
          printf(" -> %d ",cur_ptr->Data);
          cur_ptr=cur_ptr->Next;
      }
      printf("\n");
  }
}

//Reversesing a Linked List

void reverse()
{
  struct Node *prev_ptr, *cur_ptr, *temp;

  cur_ptr=Head;
  prev_ptr=NULL;

  while(cur_ptr != NULL)
  {
     temp=prev_ptr;
     prev_ptr=cur_ptr;

     cur_ptr=cur_ptr->Next;
     prev_ptr->Next=temp;
  }

  Head=prev_ptr;
}


int main(int argc, char *argv[])
{
 int i=0;

 //Set HEAD as NULL
 Head=NULL;

 while(1)
 {
    printf("\n####################################################\n");
    printf("MAIN MENU\n");
    printf("####################################################\n");
    printf(" \nInsert a number \n1. At the Beginning");
    printf(" \n2. At the End");
    printf(" \n3. At a Particular Location in the List");
    printf(" \n\n4. Print the Elements in the List");
    printf(" \n5. Print number of elements in the List");
    printf(" \n6. Reverse the linked List");
    printf(" \n\nDelete a Node in the List");
    printf(" \n7. Delete a node based on Value");
    printf(" \n8. Delete a node based on Location\n");
    printf(" \n\n9. Exit\n");
    printf(" \nChoose Option: ");
    scanf("%d",&i);

    switch(i)
    {
      case 1:
      {
          int num;
          printf(" \nEnter a Number to insert in the List: ");
          scanf("%d",&num);
          addBeg(num);
          display();
          break;
      }

      case 2:
      {
          int num;
          printf(" \nEnter the Number to insert: ");
          scanf("%d",&num);
          addEnd(num);
          display();
          break;
      }

      case 3:
      {
          int num, loc;
          printf("\nEnter the Number to insert: ");
          scanf("%d",&num);
          printf("\nEnter the location Number in List at which \
          the Number is inserted: ");
          scanf("%d",&loc);
          addAt(num,loc);
          display();
          break;
      }

      case 4:
      {
          display();
          break;
      }

      case 5:
      {
          display();
          printf(" \nTotal number of nodes in the List: %d",length());
          break;
      }

      case 6:
      {
          reverse();
          display();
          break;
      }

      case 7:
      {
          int num;
          printf(" \nEnter the number to be deleted from List: ");
          scanf("%d",&num);
          delNodeData(num);
          display();
          break;
      }

      case 8:
      {
          int num;
          printf(" \nEnter the location of the node to \
          be deleted from List: ");
          scanf("%d",&num);
          delNodeLoc(num);
          display();
          break;
      }

      case 9:
      {
          struct Node *temp;

          while(Head!=NULL)
          {
              temp = Head->Next;
              free(Head);
              Head=temp;
          }
          exit(0);
      }

      default:
      {
          printf("\nWrong Option choosen");
      }
    }/* end if switch */
 }/* end of while */
}/* end of main */

3.27.2010

Fedora 12 on HP Pavilion dv6340eu

Atlast the day has come, LINUX running on my laptop(pre-loaded with M$ VISTA). Time for celebrations.

So I decided to drop a post on how the journey took place towards installing and using LINUX in my laptop. Initially I faced a serious problem, which LINUX flavour to use ... UBUNTU or FEDORA (sorry these are only my preferred flavours for long time). I got UBUNTU successfully running on my old desktop, on my sister's latest desktop and some more desktops of friends. I got FEDORA running successfully on my SERVER and other desktops. I never tried or used LINUX flavours on a LAPTOP (as I see communities filled with posts saying problems with LINUX on their laptops) so I have to choose one ...

Atlast I decided to go with FEDORA 12 .. not sure why I dumped UBUNTU over FEDORA ... but since I am comfortable with FEDORA as I work more with FEDORA .. and FEDORA 12 got many new open-source technologies and pre-packed with latest kernel in the market (Hmm I agree that a UBUNTU release is 6 months older to a FEDORA release). But still I love UBUNTU :)

Laptop Specs
HP Pavilion dv6340eu (2007 European model)
AMD Turion 64 X2 processor,
1GB RAM (really insane),
NVIDIA GEOFORCE 7200M graphics card,
BROADCOM wireless chipset and other HP stuff.

Off the Road ... M$ VISTA
Boot up and complete M$ VISTA loading takes around 10 to 15 minutes (low RAM might be the cause) until then don't even think of opening any other application it will mess up. Sometimes I use a NOKIA mobile to connect to WIRELESS GPRS INTERNET of AIRTEL and it requires PC-SUITE software from NOKIA. Apart from this inorder to protect myself from viruses and online threats I need a third party security application(s) like ANTIVIRUS, FIREWALL (resource hogs on 1GB RAM machine running M$ VISTA). Even in idle state more than 60% of the RAM is always busy and processor(s) utilization is always more than 50%. I faced strange problems on M$ VISTA with External harddisks .. when I use "safely remove hardware" option and then disconnect the hardware it always pop up message saying some information might be lost ... eventhough I wait for sometime to disconnect them?? and it really messed up my external storage devices many times.

Back to the Road ...
I decided to go with a 32 bit FEDORA OS installation ... after seeing many problems reported with 64 bit OS when compared to 32 bit OS. Downloaded a LIVECD and installed FEDORA 12 in dual boot without any hiccups ... that's a plain install no magic spells or hacking cheats used :). Voilla great its really simple on my laptop.

Automatic reboot of laptop once the installation is complete and booted in FEDORA12 ... Wow it just took less than 2 minutes to boot up completely ... RAM and CPU usage has been drastically reduced.

I connected my NOKIA mobile to laptop and it is detected automatically. I created a new wireless broadband connection under my subscriber AIRTEL and it simply connected like a charm. Damn who needs NOKIA PC-SUITE crap for connecting to internet. I am not using any of the fancy COMPIZ stuff and simply using the NOUVEAU drivers for my graphic cards. My wirelan connection is also working like a charm no drivers from HP or any third party stuff.

Problems in Journey ..
Small usage problems with openoffice ... as my brain is corrupted with M$ OFFICE. Eventhough LIVE CD is downloaded recently it has got many security updates and patches (around 412 I guess .. of 300MB) to be downloaded from internet ... I wonder why don't they update the FEDORA build atleast once in a month with latest patches :(. Livecd doesn't have any compilers for C, C++, Java and so on and they have to be updated from internet :(. Fedora by default has music/movie players but none of them have any codecs to play a normal MP3 file (hmm licensing problems)...

Seems there are some problems with power management .. as my laptop makes me feel as if it is burning ... My harddisk temperature is at 60'c and processor cores are above 65'c eventhough internal fans are running at full speed.

After all the problems and happiness I decided to drop this post in BLOGGER from a LINUX machine ... my FIRST one. Now my laptop proudly carry the logo of FEDORA on its chest.


Update 1: Do check Fedora 12 common bugs before you install Fedora 12 on your machine - https://fedoraproject.org/wiki/Common_F12_bugs

Update 2: Integrated Webcam is still not working .. looking for workarounds.

Update 3: Do not use Nvidia Proprietary drivers replacing NOUVEAU drivers. Atleast I am seeing a system crash after update. Raised a bug at https://bugzilla.redhat.com/show_bug.cgi?id=594439 and waiting for the real reason behind the crash and any workarounds.

Hmm ... haven't found any solution until now ... Only solution available is REINSTALL OS again ... stupid workaround. Why should I stuck with FEDORA 12 which seems to be crappy .. UBUNTU 10.04 with 5 years of support here I come.

Update 4:BYE BYE FEDORA 12 .... I am really disappointed by the support and help provided by Fedora Community.