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

12.25.2012

Detecting First Node in a Loop in the List

This article is part of article series - "Datastructures"

Previous Article: Detecting a Loop in Singly Linked List - Tortoise and Hare.
Next Article: Finding Nth node from end of a Singly Linked List.

Once we confirm that there is a Loop in a Singly Linked List we will see how to determine first node of the loop.


11.13.2012

Finding Nth node from end of a Singly Linked List

This article is part of article series - "Datastructures"

Previous Article: Finding first node in a Loop in Singly Linked List.

Figure 1: Singly Linked List

Solution 01 - Brute Force Approach:
  1. Start at First Node of the List (call it curNodePtr).
  2. Assign curNodePtr to tmpPtr and count number of nodes after the curNodePtr.
  3. If number of nodes after curNodePtr are equal to N nodes or tmpPtr reaches END then break. If tmPtr reaches END but count not equal to N then return since we can't find the Nth node from the end of the Singly Linked List.
  4. Move the curNodePtr one step forward in the Linked List i.e curNodePtr now points to its next node in the list and start again from STEP-2.

11.06.2012

Reversing a Singly Linked List

This article is part of article series - "Datastructures"

Previous Article: Deleting a Node from a Singly Linked List.
Next Article: Detecting a Loop in Singly Linked List - Tortoise and Hare.

Let us see how to reverse a Singly Linked List.

Figure-1: Singly Linked List
Pseudocode:
cur_ptr = HEAD->NEXT
prev_ptr = NULL

forever:

   if cur_ptr == NULL
   break

   tmp_ptr  = prev_ptr
   prev_ptr = cur_ptr
   cur_ptr  = cur_ptr->NEXT
   
   prev_ptr->NEXT = tmp_ptr

HEAD->NEXT = prev_ptr
Complexity:
Time Complexity: O(n)
Space Complexity: O(3)

If we try on the example in Figure-1 we get the output as shown below

Figure-2: After reversing the Singly Linked List


Previous Article: Deleting a Node from a Singly Linked List.
Next Article: Detecting a Loop in Singly Linked List - Tortoise and Hare.

9.21.2012

Detecting a Loop in Singly Linked List - Tortoise & Hare

This article is part of article series - "Datastructures"

Previous Article: Reversing a Singly Linked List.
Next Article: Finding first node in a Loop in Singly Linked List.

Eventhough there are multiple algorithms available we start with

Floyd's Cycle-Finding Algorithm
In simple terms it is also known as "Tortoise and Hare Algorithm" or "Floyd's Cycle Detection Algorithm" named after its inventor Robert Floyd. It is one of the simple cycle detection algorithm. It's a simple pointers based approach.

Robert Floyd

8.23.2012

Write a C Program without main function

In a C program main function is the entry point so it is mandatory to have a main function.

But let us see how can we write a program without main (Kind of hiding main in some obfuscated code). This post is purely out of interest to know that we can do something weird like this, just for learning.


8.09.2012

Implementing ls command in C

We know that ls command in unix displays the list of files in a directory. It has various options to display the data in various styles and formats.

By default its implementation is part of Coreutils package, which is default package in all Linux flavours.

I want to see how we can implement its basic functionality with a simple C program.

7.11.2012

GIT - Adding diffmerge as visual merge in git

GIT is one of the popular distributed code repositories in opensource community, especially with developers working on opensource projects like linux kernel and others.

Operations like Merge and Diff are the most irritating & tricky tasks via command line when working on large code changes. So let us see how can we add some graphical stuff for these operations when using on GIT so that we can do merging and other options very easily. 


5.02.2012

Decoding hardware information of a PC

Checking out machine hardware information is no more a geeky thing of olden days where you need to go through the hardware specification documents or to open up a physical machine to find out the hardware details if the specification documents are missing. Now we have some really cool handy software tools to help us out.

I thought to make a page with some important tools which help us in decoding the hardware related information on a Linux Box. Feel free to drop a comment with the tool names I missed out in this post.

NOTE: All of them are ordered in alphabetical order and I am trying these tools on a Ubuntu machine running in virtual box. So some of the tool outputs might be displaying names likes VirtualBox and Oracle Corporation.
Tweak

4.05.2012

Connecting via SSH without password prompt

SSH is the common way to connect remote machines these days. Almost all kinds of applications use SSH in background for communicating with end machines.

But sometimes typing password repeatedly for establishing a SSH connection with the trusted end machine is quite daunting task.

Let us see how to automate the things in 3 simple steps where we can ssh to "user@host" without asking a password every time. Replace user with the username and host with the remote machine ip-address or hostname. For E.g. john@192.168.245.129

NOTE: Only do this with trusted machines.

3.13.2012

Daemon-izing a Process in Linux

A Linux process works either in foreground or background.

A process running in foreground can interact with the user in front of the terminal. To run a.out in foreground we execute as shown below.
./a.out
When a process runs as background process then it runs by itself without any user interaction. The user can check its status but he doesn't (need to) know what it is doing. To run a.out in background we execute as shown below.
$ ./a.out &
[1] 3665
As shown above when we run a process with & at the end then the process runs in background and returns the process id (3665 in above example).

what is a DAEMON Process?
A 'daemon' process is a process that runs in background, begins execution at startup
(not neccessarily), runs forever, usually do not die or get restarted, waits for requests to arrive and respond to them and frequently spawn other processes to handle these requests.

So running a process in BACKGROUND with a while loop logic in code to loop forever makes a Daemon ? Yes and also No. But there are certain things to be considered when we create a daemon process. We follow a step-by-step procedure as shown below to create a daemon process.

1. Create a separate child process - fork() it.
Using fork() system call create a copy of our process(child), then let the parent process exit. Once the parent process exits the Orphaned child process will become the child of init process (this is the initial system process, in other words the parent of all processes). As a result our process will be completely detached from its parent and start operating in background.
pid=fork();

if (pid<0) exit(1); /* fork error */

if (pid>0) exit(0); /* parent exits */

/* child (daemon) continues */

3.04.2012

Memory Layout of a C program - Part 2

Continuation of PART-1

As we have seen so much theory in the PART-1 now let us see a real-time example to understand about these segments. we will use size(1) command to list various section sizes in a C code.

A simple C program is given below
#include <stdio.h>

int main()
{
    return 0;
}

$ gcc test.c 
$ size a.out 
   text    data     bss     dec     hex filename
    836     260       8    1104     450 a.out
Now add a global variable as shown below
#include <stdio.h>

int global; /* Uninitialized variable stored in bss*/

int main()
{
    return 0;
}

$ gcc test.c 
$ size a.out 
   text    data     bss     dec     hex filename
    836     260      12    1108     454 a.out
As you can see BSS is incremented by 4 bytes.

Memory Layout of a C program - Part 1

A running program is called a process.

When we run a program, its executable image is loaded into memory area that normally called a process address space in an organized manner. It is organized into following areas of memory, called segments:
  • text segment 
  • data segment 
  • stack segment 
  • heap segment 
Memory layout of a C program
Figure 1: Memory layout

text segment

It is also called the code segment.

This is the area where the compiled code of the program itself resides. This is the machine language representation of the program steps to be carried out, including all functions making up the program, both user defined and system.

For example, Linux/Unix arranges things so that multiple running instances of the same program share their code if possible. Only one copy of the instructions for the same program resides in memory at any time and also it is often read-only, to prevent a program from accidentally modifying its instructions.

The portion of the executable file containing the text segment is the text section.

3.01.2012

Deletion of a Node from Doubly Linked List

This article is part of article series - "Datastructures".

Previous Article: Inserting a Node in Doubly Linked List.

Deletion of a Node 
Let us say our current Doubly Linked List is as shown in Figure-1.
Figure 1: Current Doubly Linked List

  • Deleting First Node of the List
  • Now we have to delete First Node from the List shown in Figure-1. Because of this operation HEAD and Node-2 are affected.
    In HEAD - FIRST variable should now point to NODE-2 (i.e HEAD->FIRST = HEAD->FIRST->NEXT). If you see HEAD->FIRST->NEXT actually HEAD->FIRST currently points to NODE-1 so HEAD->FIRST->NEXT is equivalent to NODE-1->NEXT which is NODE-2.
    In NODE-2 - NEXT variable remains unchanged and PREV variable should now point to NULL since it is the first Node in the List.
    Decrement LENGTH variable in HEAD so that it maintains proper count of Nodes in the List.
    Pseudocode:
    HEAD->FIRST = HEAD->FIRST->NEXT
    
    NODE-2->PREV = NULL
    
    decrement(HEAD->LENGTH)
    Output:
Figure 2: After deleting the First Node in the List.

2.27.2012

Inserting a Node in Doubly Linked List

This article is part of article series - "Datastructures"

Previous Article: Doubly Linked List                                           Next Article: Deletion of a Node from Doubly Linked List.

Insertion of a Node
Before we discuss about how to insert a NODE let us discuss few rules to follow at the time of insertion.

  • Check the location into which the user want to insert a new NODE. The possible locations where an user can insert a new node is in the range of 1 <= loc <= (length of list)+1. Let us say the length of the list is 10 & the user want to insert at location 12 (sounds stupid).

  • As we know we can traverse Bi-Directional in case of Doubly Linked Lists so we have to take care of PREV and NEXT variables in the NODE structure. We should also update the neighboring Nodes which are affected by this operation. If not we might break up the List somewhere or the other by creating a BROKEN LIST.

We have following scenarios in the case of insertion of a NODE.
  • Adding a Node at the start of the Empty List
  • Figure 1: Empty List and the newNode we want to add
    As shown in Figure-1 we have a Empty List with LENGTH set to 0 and FIRST pointing to NULL. Let us add newNode at Location 1. 
    In HEAD - FIRST variable points to newNode (head->FIRST = newNode).
    In newNode - NEXT and  PREV points to NULL as we don't have any other Nodes in the List.
    Increment the LENGTH variable in HEAD once insertion is successful to maintain the count of number of Nodes in the List.
    Pseudocode:
    HEAD->FIRST = newNode
    
    newNode->PREV = NULL
    
    newNode->NEXT = NULL
    
    increment(HEAD->LENGTH)
    Output:
Figure 2: After adding newNode in Empty List. (Changes in BLUE)

2.24.2012

Implementation of Doubly Linked List in C

In computer science, a doubly linked list is a linked data structure that consists of a set of sequentially linked records called Nodes. Each Node contains two fields, called Links, that are references to the Previous and to the Next Node in the sequence of Nodes as well as field named Data.
For every Linked List we have something called Head which marks the starting of a list. So we have two main structures namely
  • Node
  • Head

Why we need a new structure for HEAD variable ? 
Just for convenience I decided to have HEAD its own structure. You can even use the Node structure.

Node
Every Node in a Doubly Linked List has three main members namely
  • PREV
  • DATA
  • NEXT
As their names say
  • PREV - holds the memory location of the Previous Node in the List. If there are none we point towards NULL. For the First Node in the List PREV points to NULL.
  • NEXT - holds the memory location of the Next Node in the List. If there are none we point towards NULL. For the Last Node in the List NEXT points to NULL.
  • DATA - In simple words it holds Data. In our case it holds the memory location to the actual data to be held by the Node.
typedef struct node
{
    struct node *prev;
    void        *data;
    struct node *next;
}NODE;

Head
Head acts as the  "head" of the List. Head structure has two members namely
  • LENGTH - holds the count of number of Nodes in the List.
  • FIRST - hold the memory location of the first Node in the List. If the List is EMPTY it points to NULL.
typedef struct head 
{
    unsigned int length;
    struct node  *first;
}HEAD;

NOTE: Our Head structure doesn't contain any pointer to the Tail of the List. Eventhough its a best way to include a pointer to Tail Node we decided to cover that implementation in Circular Doubly Linked List.

2.11.2012

Notification Chains in Linux Kernel - Part 03

Continuation after PART-2.


Notifying Events on a Chain 
Notifications are generated with notifier_call_chain. This function simply invokes, in order of priority, all the callback routines registered against the chain. Note that callback routines are executed in the context of the process that calls notifier_call_chain. A callback routine could, however, be implemented so that it queues the notification somewhere and wakes up a process that will look at it.

NOTE: Similar to register and unregister functions we don't directly call notifier_call_chain function as we have wrapper functions for respective chains.
 <kernel/notifier.c>

 58 static int __kprobes notifier_call_chain(struct notifier_block **nl,
 59                     unsigned long val, void *v,
 60                     int nr_to_call, int *nr_calls)
 61 {
 62     int ret = NOTIFY_DONE;
 63     struct notifier_block *nb, *next_nb;
 64 
 65     nb = rcu_dereference(*nl);
 66 
 67     while (nb && nr_to_call) {
 68         next_nb = rcu_dereference(nb->next);
 69         ret = nb->notifier_call(nb, val, v);
 .
 76         nb = next_nb;
 77         nr_to_call--;
 78     }
 79     return ret;
 80 }
  • nl
    Notification chain. 

  • val
    Event type. The chain itself identifies a class of events; val unequivocally identifies an event type (i.e., NETDEV_REGISTER). 

  • v
    Input parameter that can be used by the handlers registered by the various clients. This can be used in different ways under different circumstances. For instance, when a new network device is registered with the kernel, the associated notification uses v to identify the net_device data structure.

  • nr_to_call
    Number of notifier functions to be called. Don't care value of this parameter is -1. 

  • nr_calls
    Records the number of notifications sent. Don't care value of this field is NULL.

1.16.2012

Notification Chains in Linux Kernel - Part 02

Continuation after PART-1.

Check the PART-3

Blocking Notifier chains
A blocking notifier chain runs in the process context. The calls in the notification list could be blocked as it runs in the process context. Notifications that are not highly time critical could use blocking notifier chains.

Linux modules use blocking notifier chains to inform the modules on a change in QOS value or the addition of a new device.
<kernel/notifier.c>

186 int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
187         struct notifier_block *n)
188 {
.
199     down_write(&nh->rwsem);
200     ret = notifier_chain_register(&nh->head, n);
201     up_write(&nh->rwsem);
202     return ret;
203 }
204 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register)
.
216 int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
217         struct notifier_block *n)
218 {
.
229     down_write(&nh->rwsem);
230     ret = notifier_chain_unregister(&nh->head, n);
231     up_write(&nh->rwsem);
232     return ret;
233 }
234 EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);

Notification Chains in Linux Kernel - Part 01

Linux is a monolithic kernel. Its subsystems or modules help to keep the kernel light by being flexible enough to load and unload at runtime. In most cases, the kernel modules are interconnected to one another. An event captured by a certain module might be of interest to another module.

Typically, communication systems implement request-reply messaging, or polling. In such models, a program that receives a request will have to send the data available since the last transaction. Such methods sometimes require high bandwidth or they waste polling cycles.

To fulfill the need for interaction, Linux uses so called notification chains. These notifier chains work in a Publish-Subscribe model. This model is more effective when compared to polling or the request-reply model.

For each notification chain there is a passive side (the notified) and an active side (the notifier), as in the so-called publish-and-subscribe model:
  • The notified are the subsystems that ask to be notified about the event and that provide a callback function to invoke.
  • The notifier is the subsystem that experiences an event and calls the callback function.
NOTE: All the code samples are taken from Linux 2.6.24 kernel.

struct notifier_block
The elements of the notification chain's list are of type notifier_block:
<include/linux/notifier.h>

 50 struct notifier_block {
 51     int (*notifier_call)
(struct notifier_block *, unsigned long, void *);
 52     struct notifier_block *next;
 53     int priority;
 54 };
  • notifier_call - function to execute. 
  • next - used to link together the elements of the list.
  • priority - the priority of the function. Functions with higher priority are executed first. But in practice, almost all registrations leave the priority out of the notifier_block definition, which means it gets the default value of 0 and execution order ends up depending only on the registration order (i.e., it is a semirandom order).
The notifier_block data structure is a simple linked list of function pointers. The function pointers are registered with ‘functions’ that are to be called when an event occurs. Each module needs to maintain a notifier list. The functions are registered to this notification list. The notification module (publisher) maintains a list head that is used to manage and traverse the notifier block list. The function that subscribes to a module is added to the head of the module’s list by using the register_xxxxxx_notifier API and deletion from the list is done using unregister_xxxxxx_notifier.

8.07.2010

Printing logs based on log levels in C

LOG LEVELS ??
As per my definition LOG LEVEL means a way to differentiate the importance of logs in our application. We can divide the logs into categories based on their importance and effect for e.g. ERROR logs are more important than DEBUG logs.


Why do we need to print logs based on LOG LEVEL ??
It is really helpful in projects with millions of lines of source code where the user can't use #defines or #ifdef's in order to maintain DEBUG prints. It is really tiresome to maintain #defines and #ifdef atleast for printing logs.

printk which is a part of LINUX KERNEL supports printing logs based on LOG LEVEL and it is really helpful in debugging kernel.

printf or any of its brothers & sisters don't support the option to print logs depending upon the log levels.

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.

1.04.2010

iptables - Rate-limit incoming connections


Using "recent" match option in iptables we can match recent connections, and perform simple throttling operation on incoming connections i.e. we can create simple firewall rules which will deny access from remote clients who attempt to connect "too many" times.

"recent" dynamically creates a list of IP addresses and then match against that list. The functionality of "recent" match option is simple, a list of IP addresses are created dynamically, which can be used in the future to test connection attempts against.

rate limiting is conceptually different from bandwidth throttling/limiting; a bandwidth-throttled connection will queue packets and limit the rate at which they are transmitted/received. Rate limiting will not do this; when you use rate limiting on, for example, incoming TCP connection attempts to your identd, and connections exceeding the specified limit will be denied; there is no queueing of packets.

NOTE: CONFIG_IP_NF_MATCH_RECENT flag should be enabled in Linux Kernel to use "recent" option.

Following 2 rules will limit incoming connections to destination port 22 not more than 3 in a minute and more than that will be dropped:

iptables -I INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --set

iptables -I INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --update --seconds 60 --hitcount 3 -j DROP
"--state NEW" – To make sure that only new connections are managed.

"--set" flag will make sure that the IP address of the host which initiated the connection will be added to the "recent list", where it can be tested and used again in the future i.e. in our second rule.

The second rule is where the actual magic happens.

"—update" flag tests whether the source IP address is in the list of recent connections, in our case each new tcp connection to destination port 22 will be in the list because we used the "--set" flag to add it in the preceeding rule.

"--seconds" flag is used to make sure that the source IP address is only going to match if the last connection was within the timeframe given.

"--hitcount" flag matches only if the given count of connection attempts is greater than or equal to the number given.

The second rule will DROP an incoming connection if:

  • The IP address which initiated the connection has previously been added to the list and
  • The IP address has sent a packet in the past 60 seconds and
  • The IP address has sent more than 3 packets in total.
Let use see another example where we try to limit ICMP echo requests to not more than 30 in a minute:
iptables -I INPUT -p icmp --icmp-type echo-request \
-m recent --set

iptables -I INPUT -p icmp --icmp-type echo-request \
-m recent --update --seconds 60 --hitcount 30 -j DROP
In above rules we dont use "--state NEW" since it is not needed in rate limiting number of ICMP echo requests.

NOTE: In the above rules we are trying to automatically limit number of connections from each user. So it is something like 3 attempts from each user in 1 minute.

What if we want to limit number of certain packets from all users ? Then "limit" match option comes to rescue.

"limit" option specifies the maximum average number of matches to allow per second. We can specify time intervals in the format /second, /minute, /hour, or /day, or you can use abbreviations so that 3/second is the same as 3/s.

NOTE: CONFIG_IP_NF_MATCH_LIMIT flag should be enabled in Linux Kernel to use "limit" option.

Let us see how to limit number of ICMP echo requests not more than 3 per second and drop rest of them.
iptables -I INPUT -p icmp --icmp-type echo-request \
-m limit !--limit 3/s -j ACCEPT
When tuned correctly, this feature allows us to filter unusually high volumes of traffic that characterize denial of service (DOS) attacks and Internet worms.

But take care: When tuned incorrectly, this feature does the opposite: Helping any attacker in denial of service attacks. Instead of having to initiate enough connections to bring the whole server down, it then may be sufficient to just start enough connections to activate the firewall rules.

References:
1. Debian Administration
2. man iptables

1.01.2010

Creating and using static libraries in Linux

Static libraries are simply a collection of ordinary object files.

For more information on shared libraries checkout - Creating and using shared libraries in Linux

Static libraries conventionally end with the ".a" suffix. They are useful for developers to link to their library, but don't want to give the library source code. Theoretically code in static ELF libraries that is linked into an executable should run slightly faster (by 1-5%) than a shared library or a dynamically loaded library, but in practice this rarely seems to be the case due to other confounding factors.

We use following source code files for this post.

calc_mean.c
double mean(double a, double b)
{
return (a+b) / 2;
}
calc_mean.h
double mean(double, double);
main.c - We are including our static library in this application.
#include <stdio.h>
#include "calc_mean.h"

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

double v1, v2, m;
v1 = 5.2;
v2 = 7.9;

m  = mean(v1, v2);

printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);

return 0;
}
Creating the static library

First we have to create object file for calc_mean.c
gcc -c calc_mean.c -o calc_mean.o
Then, using archiver (ar) we produce a static library (named libmean.a) out of the object file calc_mean.o.
ar rcs libmean.a calc_mean.o
NOTE: A static library must start with the three letters 'lib' and have the suffix '.a'.

Compiling main program and linking with static library

We have already created a static library libmean.a and now let us use the static library by invoking it as part of the compilation and linking process when creating a program executable. Incase of gcc we use following flags to create static library

  • -llibrary
  • searches for the library named library at the time of linking. Linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded. The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
  • -L(path-to-the-library)
  • Specifies the path in which the library file can be found. We can use -L. inorder to point to the current directory and -L/home/tmp to point to /home/tmp directory.
  • -static
  • On systems that support dynamic linking, this prevents linking with the shared libraries.
gcc -static main.c -L. -lmean -o main
Now run the executable program 'main'
$./main