Friday, 21 December 2018

Convert the string to mac address & hh format specifier


  • Use hh format specifier to convert the string into a MAC address.



int sscanf(const char *str, const char *format, ...)

Description:


  hh              Specifies that a following d, i, o, u, x, or  X
                    conversion  specifier  applies to a signed char
                    or unsigned char argument  (the  argument  will
                    have  been  promoted  according  to the integer
                    promotions, but its value shall be converted to
                    signed  char or unsigned char before printing);
                    or that  a  following  n  conversion  specifier
                    applies to a pointer to a signed char argument.


Table


ModifierModifiesApplies to
hhd, i, o, u, x, or Xchar, signed char or unsigned char
hd, i, o, u, x, or Xshort int or unsigned short int



Format specifierDescriptionSupported data types
%cCharacterchar
unsigned char
%nPrints nothing
%%Prints % character
 specifiers
lengthd iu o x Xf F e E g G a Acspn
(none)intunsigned intdoubleintchar*void*int*
hhsigned charunsigned char    signed char*
hshort intunsigned short int    short int*
llong intunsigned long int wint_twchar_t* long int*
lllong long intunsigned long long int    long long int*
jintmax_tuintmax_t    intmax_t*
zsize_tsize_t    size_t*
tptrdiff_tptrdiff_t    ptrdiff_t*
L  long double    



Program:


/* Convert the string to mac address & hh format specifier by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>
#include <stdint.h>

#define MAC_LEN   6
#define MAC_STR_BUF_LEN 32

#define MAC_INDEX_0 0
#define MAC_INDEX_1 1
#define MAC_INDEX_2 2
#define MAC_INDEX_3 3
#define MAC_INDEX_4 4
#define MAC_INDEX_5 5

typedef uint8_t    tMacAddr[MAC_LEN];

int convert_string_to_mac_address(const char *str_mac, tMacAddr mac_addr, int pattern)
{
    int  ret = 0;
    char *format = NULL;
    char str_mac_buf[MAC_STR_BUF_LEN] = {'\0'};

    switch (pattern) {
        case 0:
            format = "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx";
        break;

        case 1:
            format = "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx";
        break;

        default:
            printf("Pattern for MAC is invalid <%d> \n", pattern);
            return 0;
        break;
    }

    /* Convert the mac MAC address from string */
    ret = sscanf(str_mac, format, &mac_addr[MAC_INDEX_0], &mac_addr[MAC_INDEX_1], &mac_addr[MAC_INDEX_2],
                 &mac_addr[MAC_INDEX_3], &mac_addr[MAC_INDEX_4], &mac_addr[MAC_INDEX_5]);
    if (ret != MAC_LEN) {
        snprintf(str_mac_buf, sizeof(str_mac_buf), format,  mac_addr[MAC_INDEX_0], mac_addr[MAC_INDEX_1],
                 mac_addr[MAC_INDEX_2], mac_addr[MAC_INDEX_3], mac_addr[MAC_INDEX_4], mac_addr[MAC_INDEX_5]);
        printf("Error in converting the mac from string %s ret <%d>", str_mac_buf, ret);
        return 0;
    }

    return 0;
}


int main()
{
    tMacAddr mac1 = {0}, mac_no_colon = {0};

    convert_string_to_mac_address("00:0c:29:44:00:d3", mac1, 0);

    printf("Converted mac is <MAC:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx> \n", mac1[MAC_INDEX_0], mac1[MAC_INDEX_1], mac1[MAC_INDEX_2],
            mac1[MAC_INDEX_3], mac1[MAC_INDEX_4], mac1[MAC_INDEX_5]);


    convert_string_to_mac_address("000c294402d4", mac_no_colon, 1);
    printf("Converted mac is <MAC:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx> \n", mac_no_colon[MAC_INDEX_0], mac_no_colon[MAC_INDEX_1], mac_no_colon[MAC_INDEX_2],
            mac_no_colon[MAC_INDEX_3], mac_no_colon[MAC_INDEX_4], mac_no_colon[MAC_INDEX_5]);
    return 0;
}



  Output:

  $/sample$ ./a.out
  Converted mac is <MAC:00:0c:29:44:00:d3>
  Converted mac is <MAC:00:0c:29:44:02:d4>

Sizeof format zu or u

Sizeof format zu or u



  • It is a compile time unary operator which can be used to compute the size of its operand.
  • The result of sizeof is of unsigned integral type which is usually denoted by size_t.
  • sizeof can be applied to any data-type, including primitive types such as integer and floating-point types, pointer types, or compound datatypes such as Structure, union etc.
  • It simply return amount of memory is allocated to that data types.

 

Program:


/* sizeof by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>
 

#define STRNAME "Velraj"

int main()
{
        printf("Vel size = %zu int= %zu float = %zu double= %zu 0 = %zu NULL = %zu  \"\" = %zu int * = %zu\n",
                sizeof("vel"), sizeof(int), sizeof(float), sizeof(double), sizeof(0), sizeof(NULL), sizeof(""), sizeof(int *));

        return 0;
}

Output:

   velrajk/sample$ ./a.out
   Vel size = 4 int= 4 float = 4 double= 8 0 = 4 NULL = 8  "" = 1 int * = 8

Sunday, 11 November 2018

static use on other file compile together throws error

Static file:


  • Even if we give 2 .c file into the gcc, it will compile upto Assembler as a single .c file.
  • The below output shows that Preprocessor gave .i for 2 files.
    • Compiler gave the .s for 2 files.
    • Assembler gave the .o for 2 fileHence linker only combine these 2 .o files into a single executable file.
    • Hence we could not use the static variable in other .c file because each .c file compile separately upto .o
    • NO_STAT flag is used to remove the extern on 2nd file and make an global variable,
      • so that 2 variable are different variable even with the same name.
  • ------------ snip ---------------
  •  -r-- 1 manirathinam manirathinam   197 Nov 11 03:28 static_1.c
    -rw-rw-r-- 1 manirathinam manirathinam   171 Nov 11 03:30 static_2.c
    -rw-rw-r-- 1 manirathinam manirathinam 18382 Nov 11 03:30 static_1.i
    -rw-rw-r-- 1 manirathinam manirathinam  1174 Nov 11 03:30 static_1.s
    -rw-rw-r-- 1 manirathinam manirathinam  1392 Nov 11 03:30 static_1.o
    -rw-rw-r-- 1 manirathinam manirathinam 18398 Nov 11 03:30 static_2.i
    -rw-rw-r-- 1 manirathinam manirathinam   853 Nov 11 03:30 static_2.s
    -rw-rw-r-- 1 manirathinam manirathinam  1244 Nov 11 03:30 static_2.o
    -rwxrwxr-x 1 manirathinam manirathinam  7312 Nov 11 03:30 a.out
    manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
  •  
  • ---------------- snip --------------


Program:

File 1: static_1.c


/* static on 2 file compile together by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>

static int stat_value = 0;
// we can inclide the .c file it can able to compile successfuly.
//#include "static_2.c"



int main()
{
        printf("Inside main \n");

        return 0;
}


/* Compile :
 * Gcc working for 2 .c file:
 *     Even if we give 2 .c file into the gcc, it will compile upto Assembler as a single .c file.
 *     The below output shows that Preprocessor gave .i for 2 files.
 *                                 Compiler gave the .s for 2 files.
 *                                 Assembler gave the .o for 2 files
 *                                 Hence linker only combine these 2 .o files into a single executable file.
 *                   Hence we could not use the static variable in other .c file because each .c file compile separately upto .o
 *                   NO_STAT flag is used to remove the extern on 2nd file and make an global variable,
 *                       so that 2 variable are different variable even with the same name.
 *
 manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ ls -ltr
total 16
-rw-rw-r-- 1 manirathinam manirathinam  197 Nov 11 03:28 static_1.c
-rw-rw-r-- 1 manirathinam manirathinam  171 Nov 11 03:30 static_2.c
-rwxrwxr-x 1 manirathinam manirathinam 7312 Nov 11 03:30 a.out
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ gcc static_1.c static_2.c --save-temp
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$  ls -ltr
total 72
-rw-rw-r-- 1 manirathinam manirathinam   197 Nov 11 03:28 static_1.c
-rw-rw-r-- 1 manirathinam manirathinam   171 Nov 11 03:30 static_2.c
-rw-rw-r-- 1 manirathinam manirathinam 18382 Nov 11 03:30 static_1.i
-rw-rw-r-- 1 manirathinam manirathinam  1174 Nov 11 03:30 static_1.s
-rw-rw-r-- 1 manirathinam manirathinam  1392 Nov 11 03:30 static_1.o
-rw-rw-r-- 1 manirathinam manirathinam 18398 Nov 11 03:30 static_2.i
-rw-rw-r-- 1 manirathinam manirathinam   853 Nov 11 03:30 static_2.s
-rw-rw-r-- 1 manirathinam manirathinam  1244 Nov 11 03:30 static_2.o
-rwxrwxr-x 1 manirathinam manirathinam  7312 Nov 11 03:30 a.out
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$ gcc static_1.c static_2.c --save-temp -DNO_STAT
static_2.o: In function `add':
static_2.c:(.text+0x19): undefined reference to `stat_value'
collect2: error: ld returned 1 exit status
manirathinam@manirathinam-Aspire-E1-431:~/velraj/clan$
*/


File 2: static_2.c


/* static on 2 file compile together by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>


#ifdef NO_STAT
extern int stat_value;
#else
int stat_value;
#endif


int add()
{
        int value = 100;
        value = stat_value + value;

        return value;
}

Friday, 9 November 2018

pthread mutux deadlock for cancel handling




Program:

// C program to demonstrates cancellation of self thread
// using thread id
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>  // For memset
static pthread_mutex_t cfglock = PTHREAD_MUTEX_INITIALIZER;
int is_thread_cancel = 0, is_cleanup_push = 0;
void line_80(char ch)
{
    char str[81] = {'\0'};
    memset(str, ch, sizeof(str));
    str[80] = '\0';
    printf("%s\n", str);
    return;
}
void *calls(void* ptr)
{
    int oldtype = 0;
    printf("\nThread: Entrying into the thread %s \n", __func__);
    line_80('-');

    /* If 2 argument try then do the clean up */
    /* Add setcanceltype & cleanup into the if loop throws below error:
           error: expected ‘while’ before ‘printf’
       Reason is pthread_cleanup_push is not a function, it is a macro it cotain the below.
       So it add the d0 { on start and pthread_cleanup_pop macro contain ending while, so we could not put inside the if condition
             if (is_cleanup_push) {
     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
     do { __pthread_unwind_buf_t __cancel_buf; void (*__cancel_routine) (void *) = (pthread_mutex_unlock); void *__cancel_arg = ((void *) &cfglock); int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) __cancel_buf.__cancel_jmp_buf, 0); if (__builtin_expect ((__not_first_call), 0)) { __cancel_routine (__cancel_arg); __pthread_unwind_next (&__cancel_buf); } __pthread_register_cancel (&__cancel_buf); do {;
        }
        pthread_cleanup_pop macro definition is:
        do { } while (0); } while (0); __pthread_unregister_cancel (&__cancel_buf); if (0) __cancel_routine (__cancel_arg); } while (0);
         pthread_setcanceltype(oldtype, ((void *)0));

      */
 //  if (is_cleanup_push) {
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
        pthread_cleanup_push(pthread_mutex_unlock, (void *) &cfglock);
  //  }
    printf("Thread: Going to accquire the lock\n");
    pthread_mutex_lock(&cfglock);
    printf("Thread: Lock is accquired \n");
    printf("Thread: Going to sleep 10 second \n");
    sleep(7);
    printf("Thread: After the sleep of 10 second\n");
    /* If 2 argument try then do the clean up */
  //  if (is_cleanup_push) {
        pthread_mutex_unlock(&cfglock);
        pthread_cleanup_pop(0);
        pthread_setcanceltype(oldtype, NULL);
    //}
    printf("\nThread: Returning from thread %s \n", __func__);
    line_80('-');
    return NULL;
}

int main(int argc, char *argv[])
{
    // NULL when no attribute
    pthread_t thread = 0;
    int ret = 0;
    void *thread_ret = NULL;
    // calls is a function name
    pthread_create(&thread, NULL, calls, NULL);
    /* Argument and his valuel
          Arg 1. if 0 then no cancel, if 1 then it will call pthread_cancel.
                     Scenario: if 0 then, no cancel, thread in lock, process also try to lock, Dead lock
                     scenario 2: if 1 then , cancel kill the thread but lock is not cleaned, so proacess try to lock, hence Dead lock.
          Arg  2. if 0 then no cleanup_push for lock,
                  if 1 then do cleanup_push for lock

      */
    printf("Process: going to sleep for 3  \n");
    sleep(3);
    printf("\t\tProcess: After sleep of 3 second  \n");
    is_thread_cancel = atoi(argv[1]);
    is_cleanup_push = atoi(argv[2]);
    if (is_thread_cancel == 1) {
        /* cancelled threads do not unlock mutexes they hold */
        printf("Process: called the pthread_cancel \n");
        ret = pthread_cancel(thread);
        if (ret == 0) {
            printf("Process: Canceled the thread with ID <%ld> \n", thread);
        } else {
            printf("Process: Error in cancel while try to cancel the thread <%ld>, ret = %d \n",
                    thread, ret);
        }
    }
  //  printf("After cancel \n");

    /* Already taken the lock in thread, so this lock will be blocked */
    printf("Process: Going to acquire the Mutux  \n");
    pthread_mutex_lock(&cfglock);
    printf("\t\tProcess: Lock is acquired \n");
    pthread_mutex_unlock(&cfglock);
    printf("\t\tProcess: Mutux lock is released \n");
    printf("Process: going to sleep for 15  \n");
    sleep(10);
    printf("\t\tProcess: After sleep of 15 second  \n");
    /* The pthread_join() function waits for the thread specified by thread to terminate.
     * If that thread has already terminated, then pthread_join() returns immediately.
     * If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.
     * As per out PTHREAD_CANCELED value is 0xfffff
       */
    // Waiting for when thread is completed
//    ret = pthread_join(thread, NULL);  // Just  wati
    ret = pthread_join(thread, &thread_ret);  // Just  wati
    if (ret !=0) {
        printf("Process: Error in pthread_join errno = %d \n", ret);
    }
    printf("Process: The return value from thread is = %p \n", thread_ret);
    if (thread_ret == PTHREAD_CANCELED) {
        printf("Process: The thread is already canceled, value of PTHREAD_CANCELED  <%p>\n", PTHREAD_CANCELED);
    }
    return 0;
}

/* Ref:
        For Dedlock release lock, Solution:
                https://stackoverflow.com/questions/14268080/cancelling-a-thread-that-has-a-mutex-locked-does-not-unlock-the-mutex
       Solution method 2: For pthread_mutexattr_setrobust to releace lock:
               http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setrobust.html
               https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization
        Solution Method 1:
               https://sector7.xray.aps.anl.gov/~dohnarms/programming/glibc/html/Cleanup-Handlers.html
               https://linux.die.net/man/3/pthread_cleanup_push
*/

Tuesday, 6 November 2018

python: script to install Minimal requirements to compile the Kernel

Install the minimal requirment to compile the kernel which are declared in below sites:
      https://www.kernel.org/doc/html/v4.15/process/changes.html



Program:

# install Kernel minimal requriment compilation by Velraj.K
# Check : http://velrajcoding.blogspot.in

import subprocess
import shutil
import os

APT_INSTALL_COMMAND = "sudo apt-get --assume-yes install "
APT_UPDATE      = "sudo apt update --assume-yes"

DICT_NAME      = 'name'
DICT_CMD       = 'command'
DICT_CMD_INST  = 'command_install'

existing_sofware = []
installing_list  = []
installing_err   = []

def is_tool_present(name):
    # var = os.system('which vim') will display the output on console and store success value 0 to var
    # store the output of which in command line value into the var.
    var = os.popen('which ' + name).read()
    ret = var.find(name)
    return ret != -1


def install_software(software):
    #subprocess.call("sudo apt-get update", shell=True)
    if is_tool_present(software[DICT_CMD]):
        print(software[DICT_NAME] + " is already installed in the system, so not installing \n");
        existing_sofware.append(software)

    else:
        # run the install command in the shell,
        ret = subprocess.call(APT_INSTALL_COMMAND + software[DICT_CMD_INST], shell=True)
        # check is the software is installed successfully, if success add in installing_list otherwise add in _err.
        if ret == 0:
            print "Installed " + software[DICT_NAME] + " Successfully"
            installing_list.append(software)
        else:
            installing_err.append(software)

# Display the table header.
def table_header():
    # The value 1,20,25 & 20 are constant based on the column name
    print "{:<15} {:20} {:<20} {:<25} {:<20}".format('Package', '\"Command Name\"', '\"Newly Installed\"', '\"Error while installing\"', '\"Existing package\"')
    line = []
    for i in range(1, 82):
        # creat the list with - for display a line
        line.append('-')
    # convert the list into a string other wise display as ['-', '-', '-', ...]
    str1 = ''.join(str(e) for e in line)
    print str1

# To display the row content in the table
def table_row(table_row):
    # The value 22, 23,23 & 20 are constant based on the column adjust value row
        print "{:<22} {:<22} {:<23} {:<23} {:<20}".format(table_row[0], table_row[1], table_row[2], table_row[3], table_row[4])


def result_tablular():
    # Display the result table header
    table_header()
    # Display the row value in the tabl
    for name in installing_list:
        table_row([name[DICT_NAME], name[DICT_CMD_INST], 'Yes', 'NA', 'NA'])

    for name in installing_err:
        table_row([name[DICT_NAME], name[DICT_CMD_INST], 'NA', 'Yes', 'NA'])

    for name in existing_sofware:
        table_row([name[DICT_NAME], name[DICT_CMD_INST], 'NA', 'NA', 'Yes'])

def main():
    software_name = ['gcc', 'make', 'ld', 'fdformat', 'depmod', 'e2fsck',
                     'pccardctl', 'pppd', 'ps', 'iptables', 'openssl', 'bc',
                     'fsck.jfs', 'reiserfsck', 'xfs_db', 'mksquashfs', 'btrfsck',
                     'quota', 'iudnctrl', 'showmount', 'oprofiled', 'udevd', 'grub',
                     'mcelog', 'sphinx-build' ]

    dict_list_software = [ {DICT_NAME:'GNU C', DICT_CMD:'gcc', DICT_CMD_INST:'gcc'},
                       {DICT_NAME:'GNU make', DICT_CMD:'make', DICT_CMD_INST:'make'},
                       {DICT_NAME:'binutils', DICT_CMD:'ld', DICT_CMD_INST:'binutils'},
                       {DICT_NAME:'util-linux', DICT_CMD:'fdformat', DICT_CMD_INST:'util-linux'},
                       {DICT_NAME:'module-init-tools', DICT_CMD:'depmod', DICT_CMD_INST:'module-init-tools'},
                       {DICT_NAME:'e2fsprogs', DICT_CMD:'e2fsck', DICT_CMD_INST:'e2fsprogs'},
                       {DICT_NAME:'jfsutils', DICT_CMD:'fsck.jfs', DICT_CMD_INST:'jfsutils'},
                       {DICT_NAME:'reiserfsprogs', DICT_CMD:'reiserfsck', DICT_CMD_INST:'reiserfsprogs'},
                       {DICT_NAME:'xfsprogs', DICT_CMD:'xfs_db', DICT_CMD_INST:'xfsprogs'},
                       {DICT_NAME:'squashfs-tools', DICT_CMD:'mksquashfs', DICT_CMD_INST:'squashfs-tools'},
                       {DICT_NAME:'btrfs-progs', DICT_CMD:'btrfsck', DICT_CMD_INST:'btrfs-progs'},
                       {DICT_NAME:'pcmciautils', DICT_CMD:'pccardctl', DICT_CMD_INST:'pccardctl'},
                       {DICT_NAME:'quota-tools', DICT_CMD:'quota', DICT_CMD_INST:'quota'},
                       {DICT_NAME:'PPP', DICT_CMD:'pppd', DICT_CMD_INST:'pppd'},
                       {DICT_NAME:'isdn4k-utils', DICT_CMD:'isdnctrl', DICT_CMD_INST:'isdnutils-base'},
                       {DICT_NAME:'nfs-utils', DICT_CMD:'showmount', DICT_CMD_INST:'nfs-common'},
                       {DICT_NAME:'procps', DICT_CMD:'ps', DICT_CMD_INST:'procps'},
                       {DICT_NAME:'oprofile', DICT_CMD:'oprofiled', DICT_CMD_INST:'oprofile'},
                       {DICT_NAME:'udev', DICT_CMD:'udevd', DICT_CMD_INST:'udev'},
                       {DICT_NAME:'grub', DICT_CMD:'grub', DICT_CMD_INST:'grub-pc'},
                       {DICT_NAME:'mcelog', DICT_CMD:'mcelog', DICT_CMD_INST:'mcelog'},
                       {DICT_NAME:'iptables', DICT_CMD:'iptables', DICT_CMD_INST:'iptables'},
                       {DICT_NAME:'openssl & libcrypto', DICT_CMD:'openssl', DICT_CMD_INST:'openssl'},
                       {DICT_NAME:'bc', DICT_CMD:'bc', DICT_CMD_INST:'bc'},
                       {DICT_NAME:'Sphinx', DICT_CMD:'sphinx', DICT_CMD_INST:'python-sphinx'} ]
    ret = subprocess.call(APT_UPDATE, shell=True)
    # Check and install the list of software available in the software_name
    for name in dict_list_software:
        install_software(name)

    # Package installed due to kernal compilation error
    # sign-file.c:25:30: fatal error: openssl/opensslv.h: No such file or directorycompilation terminated.
    #    for install libssl-dev
    dict_list_soft_cmp_err = [ {DICT_NAME:'OpenSSL Dev pkg', DICT_CMD:'libssl-dev', DICT_CMD_INST:'libssl-dev'} ]
    for name in dict_list_soft_cmp_err:
       install_software(name)


    result_tablular()

if __name__ == "__main__":
    main()

python: script to check Minimal requirements to compile the Kernel

Used to check the minimal requirment to compile the kernel which are declared in below sites:
      https://www.kernel.org/doc/html/v4.15/process/changes.html


Program:

# Kernel minimal requriment check by Velraj.K
# Check : http://velrajcoding.blogspot.in

import subprocess
import shutil
import os

APT_INSTALL_COMMAND = "sudo apt-get --assume-yes install "
APT_UPDATE      = "sudo apt update --assume-yes"

DICT_NAME      = 'name'
DICT_CMD       = 'command'
existing_sofware = []
not_available_list  = []
installing_err   = []

def is_tool_present(name):
    # var = os.system('which vim') will display the output on console and store success value 0 to var
    # store the output of which in command line value into the var.
    var = os.popen('which ' + name).read()
    ret = var.find(name)
    return ret != -1


def install_software(software):
    # Check the command is present in Linux OS
    if is_tool_present(software[DICT_CMD]):
        existing_sofware.append(software)
    else:
        not_available_list.append(software)

# Display the table header.
def table_header():
    # The value 1,20,25 & 20 are constant based on the column name
    print "{:<20} {:<15} {:<20} {:<20}".format('Program Name', '\"Command\"', '\"Available\"', '\"Not available\"')
    line = []
    for i in range(1, 72):
        # creat the list with - for display a line
        line.append('-')
    # convert the list into a string other wise display as ['-', '-', '-', ...] 
    str1 = ''.join(str(e) for e in line)
    print str1

# To display the row content in the table
def table_row(table_row):
    # The value 22, 23,23 & 20 are constant based on the column adjust value row
        print "{:<23} {:<15} {:<21} {:<20}".format(table_row[0], table_row[1], table_row[2], table_row[3])


def result_tablular():
    # Display the result table header
    table_header()
    # Display the row value in the tabl
    for name in existing_sofware:
        table_row([name[DICT_NAME], name[DICT_CMD], 'Yes', 'NA'])
    for name in not_available_list:
        table_row([name[DICT_NAME], name[DICT_CMD], 'NA', 'Yes'])


def main():

    # Dictionary usage example: 
    #    myStruct = {'field1': 'some val', 'field2': 'some val'}
    #    print myStruct['field1']
    #    myStruct['field2'] = 'some other values'
    # List of Minimum requirement package
    dict_list_software = [ {DICT_NAME:'GNU C', DICT_CMD:'gcc'},
                           {DICT_NAME:'GNU make', DICT_CMD:'make'},
                           {DICT_NAME:'binutils', DICT_CMD:'ld'},
                           {DICT_NAME:'util-linux', DICT_CMD:'fdformat'},
                           {DICT_NAME:'module-init-tools', DICT_CMD:'depmod'},
                           {DICT_NAME:'e2fsprogs', DICT_CMD:'e2fsck'},
                           {DICT_NAME:'jfsutils', DICT_CMD:'fsck.jfs'},
                           {DICT_NAME:'reiserfsprogs', DICT_CMD:'reiserfsck'},
                           {DICT_NAME:'xfsprogs', DICT_CMD:'xfs_db'},
                           {DICT_NAME:'squashfs-tools', DICT_CMD:'mksquashfs'},
                           {DICT_NAME:'btrfs-progs', DICT_CMD:'btrfsck'},
                           {DICT_NAME:'pcmciautils', DICT_CMD:'pccardctl'},
                           {DICT_NAME:'quota-tools', DICT_CMD:'quota'},
                           {DICT_NAME:'PPP', DICT_CMD:'pppd'},
                           {DICT_NAME:'isdn4k-utils', DICT_CMD:'isdnctrl'},
                           {DICT_NAME:'nfs-utils', DICT_CMD:'showmount'},
                           {DICT_NAME:'procps', DICT_CMD:'ps'},
                           {DICT_NAME:'oprofile', DICT_CMD:'oprofiled'},
                           {DICT_NAME:'udev', DICT_CMD:'udevd'},
                           {DICT_NAME:'grub', DICT_CMD:'grub'},
                           {DICT_NAME:'mcelog', DICT_CMD:'mcelog'},
                           {DICT_NAME:'iptables', DICT_CMD:'iptables'},
                           {DICT_NAME:'openssl & libcrypto', DICT_CMD:'openssl'},
                           {DICT_NAME:'bc', DICT_CMD:'bc'},
                           {DICT_NAME:'Sphinx', DICT_CMD:'sphinx-build'} ]

    # Check and install the list of software available in the software_name
    for name in dict_list_software:
        install_software(name)

    result_tablular()

if __name__ == "__main__":
    main()

Monday, 5 November 2018

python: script to install C Linux development needed packages

The Following C linux development packages are installed using python script:
  • Vim
  • cscope
  • screen
  • make
  • cmake
  • gdb
  • gcc


Program:



import subprocess
import shutil
import os

APT_INSTALL_COMMAND = "sudo apt-get --assume-yes install "
APT_UPDATE      = "sudo apt update --assume-yes"

existing_sofware = []
installing_list  = []
installing_err   = []

def is_tool_present(name):
    # var = os.system('which vim') will display the output on console and store success value 0 to var
    # store the output of which in command line value into the var.
    var = os.popen('which ' + name).read()
    ret = var.find(name)
    return ret != -1

def install_software(software):
    #subprocess.call("sudo apt-get update", shell=True)
    if is_tool_present(software):
        print(software + " is already installed in the system, so not installing \n");
        existing_sofware.append(software)

    else:
        # run the install command in the shell,
        ret = subprocess.call(APT_INSTALL_COMMAND + software, shell=True)
        # check is the software is installed successfully, if success add in installing_list otherwise add in _err.
        if ret == 0:
            print "Installed " + software + " Successfully"
            installing_list.append(software)
        else:
            installing_err.append(software)

# Display the table header.
def table_header():
    # The value 1,20,25 & 20 are constant based on the column name
    print "{:<15} {:<20} {:<25} {:<20}".format('Package', '\"Newly Installed\"', '\"Error while installing\"', '\"Existing package\"')
    line = []
    for i in range(1, 82):
        # creat the list with - for display a line
        line.append('-')
    # convert the list into a string other wise display as ['-', '-', '-', ...]
    str1 = ''.join(str(e) for e in line)
    print str1

# To display the row content in the table
def table_row(table_row):
    # The value 22, 23,23 & 20 are constant based on the column adjust value row
        print "{:<22} {:<23} {:<23} {:<20}".format(table_row[0], table_row[1], table_row[2], table_row[3])


def result_tablular():
    # Display the result table header
    table_header()
    # Display the row value in the tabl
    for name in installing_list:
        table_row([name, 'Yes', 'NA', 'NA'])

    for name in installing_err:
        table_row([name, 'NA', 'Yes', 'NA'])

    for name in existing_sofware:
        table_row([name, 'NA', 'NA', 'Yes'])

def main():
    # The follwoing software used for automake
    #      automake, automake1.11
    #      libtool --> Used in automake file as libtoolize command
    # binutils-dev --> includes header files and static libraries necessary to build programs which use the GNU BFD library
    # build-essential --> for libc-devel
    software_name = ['vim', 'cscope', 'screen', 'make', 'cmake', 'gdb', 'gcc', 'git', 'automake', 'libtool',
                     'binutils-dev', 'libc6', 'build-essential']

    ret = subprocess.call(APT_UPDATE, shell=True)
    # Check and install the list of software available in the software_name
    for name in software_name:
        install_software(name)

    result_tablular()

if __name__ == "__main__":
    main()

  

Tuesday, 16 October 2018

Reverse the given sentence

Reverse the give sentence:


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

#define STR_BUFFER_256    256
#define ARG_LENGTH        64


int reverse_sentence(char *str, char *str_result, int str_len)
{
        char str_sentence[STR_BUFFER_256] = {'\0'};
        char *arg[ARG_LENGTH] = {0}, *temp = NULL;
        int count = 0, rev_count;

#if 0 // This logic is wrong because strncpy won't return a number of byte written
        int ret = 0;

        ret = strncpy(str_sentence, str, sizeof(STR_BUFFER_256));
        if (ret >= STR_BUFFER_256) {
                printf("Truncation the sentence \n");
        }
#else
        memset(str_sentence, '\0', str_len);
        strncpy(str_sentence, str, str_len);

        if (str_sentence[STR_BUFFER_256 - 1] != '\0') {
                printf("Truncation the sentence \n");
        }

#endif

#ifdef DEBUG
        printf("Original = %s copied varable = %s \n", str, str_sentence);
#endif
        temp = strtok(str_sentence, " ");
        arg[count] = temp;
        count++;

        while (temp && (count < ARG_LENGTH)) {
                temp = strtok(NULL, " ");
                arg[count] = temp;
                count++;
        }


        if (temp && (count >= ARG_LENGTH)) {
                temp = strtok(NULL, " ");
                if (temp != NULL) {
                        printf("No of word is more than %d so taking first %d word only\n", ARG_LENGTH, ARG_LENGTH);
                }
        }

        /* arg[count] last value will be a NULL, but count is point to next to NUll */
        count--;

       /* Count point the sentinal value, decerement to point to the last word */
        count--;
#ifdef DEBUG
        printf("inst cout = %d rev c= %d \n", count, rev_count);
#endif
        for (rev_count = count; rev_count >= 0 ; rev_count--) {
                strncat(str_result, arg[rev_count], str_len);
                if (rev_count != 0) {
                        strncat(str_result, " ", str_len);
                }
        }

        return 0;
}

int main()
{
        char str[STR_BUFFER_256] = "Velraj is coming from chennai";
        char str_result[STR_BUFFER_256] = {'\0'};

        reverse_sentence(str, str_result, sizeof(str_result));
        printf("\n\t\t Original sentence = %s \n\t\t Reverse sentence = %s \n", str, str_result);

        return 0;
}

/* Output:
   ------
   velraj@velraj-HEC41:~/CProgram$ gcc -g sentence_reverse_hcl.c
   velraj@velraj-HEC41:~/CProgram$ ./a.out

   Original sentence = Velraj is coming from chennai
   Reverse sentence = chennai from coming is Velraj
   velraj@velraj-HEC41:~/CProgram$

   '-g' is used to include the symbols, if we need to debug with gdb then compile with -g only give the
   symbol value.

 */

Tuesday, 9 October 2018

Difference between 2 jiffies

What is jiffies:


  • The original kernel timer system (called the "timer wheel) was based on incrementing a kernel-internal value (jiffies) every timer interrupt.
  • The timer interrupt rate (and jiffy increment rate) is defined by a compile-time constant called HZ.
  • Different platforms use different values for HZ.
  • The kernel used 100 as the value for HZ, yielding a jiffy interval of 10 ms.
  • With 2.4, the HZ value for i386 was changed to 1000, yeilding a jiffy interval of 1 ms.
  • Process:
    • When jiffy count is incremented then a process gets time to run.
    • The jiffies are incremented by the timer interrupt that tells the scheduler to reschedule
    •  If the process calls yield() or sleep(), for example, then rescheduling takes place immediately.
    • Thus the context switch to a next available running process not necessarily occurs at the jiffy boundary.
  • It lists /proc/timer_list and /proc/timer_stats.
  • Tick generation:
    • It is updated every tick 
    • tick is triggered by timer/clock interrupt.
    • The interrupt is generated by Intel 8253 or HPET hardware
    • So it won't update until the hardware was property initialized.
  • Difference:
    • There is a better solution to ensure correct jiffy wrap handling in *ALL* kernel code: make jiffy wrap in first five minutes of uptime.
    • #define INITIAL_JIFFIES (0xffffffffUL & (unsigned long)(-300*HZ))
    • Hence jiffies is using the full 32 bit, after that overflow happen.
    • So jiffies.h file comment as maximum jiffie value is (MAX_INT >> 1) is a false comment.
    • Don't use MAX_JIFFY_OFFSET as max value since this is wrong.
    • https://lwn.net/Articles/22874/

Program:


Wrong program:

  • This below code is wrong, because jiffies is using the full 32 bit confirmed by after bootup jiffies overflow in 5 min, 
  • So after bootup just checked the jiffies value, it is using full 32 bit before overflow.
  • Hence below code is wrong, this is wrongly used in some of kernel code.

inline unsigned long jiffies_time_diff(unsigned long start, unsigned long end)
{
    if (end >= start)
        return end - start;
    return end + (MAX_JIFFY_OFFSET - start);
}

Correct program:


inline unsigned long jiffies_time_diff(unsigned long start, unsigned long end)
{  
       unsigned long diff = 0;

       /* This code is handle the overflow also, by converting to long.
            if jiffies start time is 13 and after overflowed end time is 5 then, coverting to sign
            difference value is -8, the 1st complement +1 value of -8 is stored as big value in unsiged diff.
            This is the correct difference */
       diff = (long)end - (long) start;
       return diff;
}
        

Sunday, 7 October 2018

What does _r suffix mean?


  • The suffix "_r" is historical, where the 'r' stood for "reentrant".
  • A computer program or subroutine is called reentrant.
    • if it can be interrupted in the middle of its execution and then safely be called again ("re-entered") before its previous invocations complete execution. 

  • Using global variable inside the function, ISR(interuppt call) may try to access our temporary changed global value in outside.
    • Solution:
      • Use the local variable instead of global variable will clear this issue
    • _r reason:
      • Using _r to make sure global variables are not affected.

  • _r function will be thread safe.
  • EG: strtok vs strtok_r



Return:
The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more tokens.

Attributes:
For an explanation of the terms used in this section, see attributes(7). ┌───────────┬───────────────┬───────────────────────┐ │InterfaceAttributeValue │ ├───────────┼───────────────┼───────────────────────┤ │strtok() │ Thread safety │ MT-Unsafe race:strtok │ ├───────────┼───────────────┼───────────────────────┤ │strtok_r() │ Thread safety │ MT-Safe │ └───────────┴───────────────┴───────────────────────┘

Program:


/* strtok vs strtok_r by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
    char *str1, *str2, *token, *subtoken;
    char *saveptr1, *saveptr2;
    char str_second[256] = {'\0'};
    int j;
    if (argc != 4) {
        fprintf(stderr, "Usage: %s string delim subdelim\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }
    strncpy(str_second, argv[1], sizeof(str_second));
    printf("\n\n\t\t Do the token using strtok_r \n");
    /* use strtok_r */
    for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
        token = strtok_r(str1, argv[2], &saveptr1);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok_r(str2, argv[3], &saveptr2);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
    }
    printf("Original value = %s \n", argv[1]);

    printf("\n\n\t\tDo the token using strtok str_second = %s \n", str_second);
    /* Initialize the variable to NULL to start token again with strtok */
    str1 = NULL;
    str2 = NULL;
    token = NULL;
    subtoken = NULL;
    saveptr1 = NULL;
    saveptr2 = NULL;
    /* use strtok */
    for (j = 1, str1 = str_second; ; j++, str1 = NULL) {
        token = strtok(str1, argv[2]);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
#if 0 // Could not use the 2nd strtok with different delim because it uses the global pointer
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok(str2, argv[3]);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
#endif
    }
    exit(EXIT_SUCCESS);
}


Output:


learn$ ./a.out this,isvelraj,check,strok,new , .

                 Do the token using strtok_r
1: this
 --> this
2: isvelraj
 --> isvelraj
3: check
 --> check
4: strok
 --> strok
5: new
 --> new
Original value = this

                Do the token using strtok str_second = this,isvelraj,check,strok,new
1: this
2: isvelraj
3: check
4: strok
5: new