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

9.15.2009

Signals in Linux - Catching and Ignoring Signals - signal

The simplest way to change the action for a signal is to use the signal system call. You can specify a built-in action (such as to ignore the signal), or you can establish a handler.
#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler)

signal sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer-defined function (a "signal handler").

NOTE: The signals SIGKILL and SIGSTOP cannot be caught or ignored. The effects of signal system call in a multithreaded process are unspecified.

For more information checkout: man 2 signal

NOTE: The behavior of signal system call varies across different UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction system call instead. Check man 2 signal for detailed information about various portability issues.

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

static volatile sig_atomic_t doneflag = 0;

static void setdoneflag(int signo) {
printf("\nIn SignalHandler - setdoneflag\n");
doneflag = 1;
}

int main (void) {

signal(SIGINT, setdoneflag);

while (!doneflag) {
printf("press CTRL+C to kill the Loop\n");
sleep(1);
}

printf("Program terminating ...\n");
return 0;
}

Output:

$ ./a.out
press CTRL+C to kill the Loop
press CTRL+C to kill the Loop
press CTRL+C to kill the Loop
^C
In SignalHandler - setdoneflag
Program terminating ...
$

9.08.2009

Reading a string of length 'n' from Standard Input [STDIN]

We know how to read a string from STDIN in C by using library functions like scanf, fgets and so on. By using these functions there is a chance for memory corruption and strange behaviour. For example while using scanf if we try to save a string of length more than the variable size there is a chance of memory corruption.

So here in this post I am just trying to implement a function capable to read a string of length 'n' from STDIN without memory corruption and other bugs.

Do help me by checking the code if there is a chance for further improvements.

#include <stdio.h>
#include <string.h>

#define BUF_SIZE 6
#define STRING_SIZE 4

/*
* void getStringStdin(char *, int , int );
*
* 1: BUF :Pointer to the array of characters where input string
is to be stored.
* 2: BUF_LEN :Is the length of the array of characters where the
string is stored.buffer where we save the string.
* 3: STRING_LEN :Is the length of the string.
*
* NOTE: STRING_LEN < BUF_LEN
*
*/

getStringStdin(char *buf, int buf_len, int str_len)
{
int ch, len;
char *s;

if(str_len>=buf_len)
len=buf_len-1;
else
len=str_len;

printf ("\nEnter string of length %d(Remaining is ignored): ",len);

if( (fgets(buf, len+1, stdin)) != NULL )
{
s=my_strchr(buf,'\n');

if(s!=NULL)
{
*s='\0';
}
else
{
while ((ch = getchar()) != '\n' && ch != EOF);
}
}
}

int main(void)
{
int i=0;
char buf[BUF_SIZE];

do
{
getString(buf, BUF_SIZE, STRING_SIZE);
printf ("\nString : %s\n", buf);
i++;
}while(i<2);

return 0;
}

How to: Listing all users in a Linux machine

TO list all the users who can access a Linux machine we have to access the /etc/passwd file, which stores information about all registered users of that machine. But it is not really so easy as told above since the file contains many other fields & machine trust accounts & inbuilt accounts.

We'll start by
cat /etc/passwd 

As we all know that by default all the users created will have their home directories in /home share so we'll modify our command a bit by using grep. Now it'll be
cat /etc/passwd | grep "/home"

Now we'll get all the user accounts which have their home share in /home.But the only output we need is the list of users & nothing else. So we'll modify our command again
cat /etc/passwd | grep "/home" |cut -d: -f1
Now what we have done is that we have piped the output of previous command to another variable "cut"

What we have done here is we have added cut -d: -f1
-d: means delimiter :
-f1 means display first field of line i.e. username.

So final command is
cat /etc/passwd | grep "/home" |cut -d: -f1
This works until all your users have their home share in /home. If you have defined their home share to some other destination. Modify the above command accordingly.

9.02.2009

Signals in Linux - Generating Signals

Besides signals that are generated as a result of a hardware trap or interrupt, your program can explicitly send signals to itself or to another process.

The kill system call can be used to send any signal to any process group or process.
#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

For more information checkout: man 2 kill

There are restrictions that prevent you from using kill to send signals to any random process. These are intended to prevent antisocial behavior such as arbitrarily killing off processes belonging to another user. In typical use, kill is used to pass signals between parent, child, and sibling processes, and in these situations you normally do have permission to send signals. The only common exception is when you run a setuid program in a child process; if the program changes its real UID as well as its effective UID, you may not have permission to send a signal. The su program does this.

A process or thread can send a signal to itself with the raise function. The raise function takes just one parameter, a signal number.

In a single-threaded program it is equivalent to kill(getpid(), sig). In a multithreaded program it is equivalent to pthread_kill(pthread_self(), sig). If the signal causes a handler to be called, raise will only return after the signal handler has returned.
#include <signal.h>

int raise(int sig);

For more information checkout: man 3 raise
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static volatile sig_atomic_t doneflag = 10;

static void setdoneflag(int signo) {
printf("\nIn SignalHandler - setdoneflag\n");
doneflag=0;
}

int main (void) {

signal(SIGINT, setdoneflag);

while(doneflag--)
{
printf("In While loop - %d\n",doneflag);
if(doneflag==5)
raise(2);
else
sleep(1);
}

printf("Program terminating ...\n");
return 0;
}

8.26.2009

Implementation of Singly Linked List

This article is part of article series - "Datastructures"

Generally a Linked List means "Singly Linked List". It is a chain of records known as Nodes. Each node has at least two members, one of which points to the next Node in the list and the other holds the data.

Figure 1: Singly Linked List
Basically Single Linked Lists are uni-directional as they can only point to the next Node in the list but not to the previous. We use below structure for a Node in our example.
 struct Node
 {
   int Data;
   struct Node *Next;
 }; 
Variable Data holds the data in the Node (It can be a pointer variable pointing to the dynamically allocated memory) while Next holds the address to the next Node in the list.

Figure 2: Node in a Singly Linked List
Head is a pointer variable of type struct Node which acts as the Head to the list. Initially we set 'Head' as NULL which means list is empty.