How to troubleshoot dns issues by directly querying name servers

This tip will help you troubleshooting DNS issues by directly querying DNS using only the IP address of name servers. When you run dns resolution client tools such as dig or nslookup, they will query the name server configured on your host. If the DNS with unexpired ttl is in cache, they will return it from cache. The results will return from cache by any of the intermediate name servers except for the authoritative name servers. That is why ‘dig +trace’ is useful in troubleshooting dns issues, as it starts from the root name servers and moves down all the way to the authoritative name servers to get you the dns records.

Here is a similar tool to “dig +trace”, which queries root name servers, their IPs is hard coded in the script, and follows the authoritative name servers for the subdomains by directly querying the registered IP addresses of name servers. For instance, if you use this tool to query “www.example.com”, it will get a randomly picked root name server’s IP and query it for NS records of “.com” domain. Once it gets the IP address of the name servers for “.com”, it goes on to query them for authoritative name servers of “example.com.” and does the same for “www.example.com.” as well. Throughout the query, it doesn’t use any cache or FQDN, it get the IP address of authoritative name servers and queries the IP directly.

You will need to install dnspython module first –

cd /tmp
pip install dnspython
https://github.com/danasmera/Python_scripts.git
cd Python_scripts/

Start DNS tracing now –

1. google.com

$ python dig-trace.py google.com
Splitting domain into sub-domains ...
['.', 'com.', 'google.com.']

Selected root . name server: 199.9.14.201
Selecting name server for com. domain ...

picked name server: 192.48.79.30
Selecting name server for google.com. domain ...

picked name server: 216.239.36.10
Querying name server: 216.239.36.10
google.com. 300 IN A 173.194.219.102
google.com. 300 IN A 173.194.219.101
google.com. 300 IN A 173.194.219.113
google.com. 300 IN A 173.194.219.100
google.com. 300 IN A 173.194.219.138
google.com. 300 IN A 173.194.219.139


2. www.whitegov.com txt

 python dig-trace.py www.whitegov.com txt
Splitting domain into sub-domains ...
['.', 'com.', 'whitegov.com.', 'www.whitegov.com.']

Selected root . name server: 192.33.4.12
Selecting name server for com. domain ...

picked name server: 192.54.112.30
Selecting name server for whitegov.com. domain ...

picked name server: 204.11.57.26
Selecting name server for www.whitegov.com. domain ...

picked name server: 204.11.56.26
Querying name server: 204.11.56.26
www.whitegov.com. 3600 IN TXT "~"



3. cnn.com mx

$ python dig-trace.py cnn.com mx
Splitting domain into sub-domains ...
['.', 'com.', 'cnn.com.']

Selected root . name server: 193.0.14.129
Selecting name server for com. domain ...

picked name server: 192.31.80.30
Selecting name server for cnn.com. domain ...

picked name server: 205.251.192.47
Querying name server: 205.251.192.47
cnn.com. 300 IN MX 10 mxa-000c6b02.gslb.pphosted.com.
cnn.com. 300 IN MX 10 mxb-000c6b02.gslb.pphosted.com.

4. linuxfreelancer.com [ANY | NS ]

$ python dig-trace.py www.linuxfreelancer.com ANY
Splitting domain into sub-domains ...
['.', 'com.', 'linuxfreelancer.com.', 'www.linuxfreelancer.com.']

Selected root . name server: 192.112.36.4
Selecting name server for com. domain ...

picked name server: 192.35.51.30
Selecting name server for linuxfreelancer.com. domain ...

picked name server: 208.109.255.48
Selecting name server for www.linuxfreelancer.com. domain ...
Querying name server: 208.109.255.48


$ python dig-trace.py www.linuxfreelancer.com NS
Splitting domain into sub-domains ...
['.', 'com.', 'linuxfreelancer.com.', 'www.linuxfreelancer.com.']

Selected root . name server: 202.12.27.33
Selecting name server for com. domain ...

picked name server: 192.55.83.30
Selecting name server for linuxfreelancer.com. domain ...

picked name server: 216.69.185.48
Selecting name server for www.linuxfreelancer.com. domain ...
Querying name server: 216.69.185.48
www.linuxfreelancer.com. 1800 IN CNAME linuxfreelancer.com.
linuxfreelancer.com. 3600 IN NS ns75.domaincontrol.com.
linuxfreelancer.com. 3600 IN NS ns76.domaincontrol.com.


Links –

https://github.com/rthalley/dnspython

https://github.com/danasmera/Python_scripts

How to update or change author name or email in git or github

Under rare circumstances, your commits in github might show appear in github as if they were made by some one else. I was once the sole contributor in a personal repo and when I pushed a commit to github, I noticed that the in github the commit appeared to come from some other github member and that member was added as a contributor in my repo. The reason for this issue was in my local git config, I had my email address as “user@localhost.localdomain”. Apparently github links your commit to whoever setup that email address to their GitHub account.

Here is the steps and a script that you can run to fix this –

1. Clone your github repo to your local file system.
2. change to the cloned directory
3. Add below shell script to your repo directory and run it –
Make sure to update the first three variables OLD_EMAIL, CORRECT_NAME, and CORRECT_EMAIL to appropriate values.

#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="ADD_EMAIL_TO_BE_REMOVED@HERE.COM"
CORRECT_NAME="NEW_CORRECT_NAME"
CORRECT_EMAIL="NEW_CORRECT_EMAIL@HERE.COM"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

4. Run ‘git log’ to review the author information and if everything looks good –

git push --force --tags origin 'refs/heads/*'

5. delete the cloned directory from your local file system.

References –

https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/

https://help.github.com/articles/changing-author-info/

Top 10 basic Linux commands for beginners

1. id – display information about user.

id will print the user and group information of the given argument, if no argument is given, it will show the information of the currently logged in user.

$ id
uid=1000(daniel) gid=1000(daniel) groups=1000(daniel),4(adm),27(sudo)
$ id -u -n
daniel
$ id root
uid=0(root) gid=0(root) groups=0(root)
$ id sshd
uid=110(sshd) gid=65534(nogroup) groups=65534(nogroup)
 

2. ls – list files in a directory.

ls lists the contents of current directory if not arguments are given. It has probably one of the largest number of options compared to other Linux commands.

$ pwd            # our current working directory
/home/daniel/projects
$ ls             # content of current directory
demo.txt  mail  nfs  redhat  samba
$ ls -l          # long listing
total 20
-rw-rw-r-- 1 daniel daniel   21 Apr 15 01:04 demo.txt
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 mail
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 nfs
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 redhat
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 samba
$ ls -1         # list one file per line
demo.txt
mail
nfs
redhat
samba
$ ls -a        # show all, including ones starting with . (dot)
.  ..  demo.txt  .hidden  mail  nfs  redhat  samba
$ ls -al       # long listen plus show all 
total 32
drwxrwxr-x  6 daniel daniel 4096 Apr 15 01:04 .
drwxr-xr-x 18 daniel daniel 4096 Apr 15 01:06 ..
-rw-rw-r--  1 daniel daniel   21 Apr 15 01:04 demo.txt
-rw-rw-r--  1 daniel daniel   32 Apr 15 01:03 .hidden
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:04 mail
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:04 nfs
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:04 redhat
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:04 samba
#  ls --format=verbose    # same as ls -l
total 20
-rw-rw-r-- 1 daniel daniel   21 Apr 15 01:04 demo.txt
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 mail
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 nfs
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 redhat
drwxrwxr-x 2 daniel daniel 4096 Apr 15 01:04 samba
$ ls -F                  # classify: / for directory, * for executable, @ for symbolic link
demo-link@  demo.txt  mail/  nfs/  redhat/  run.sh*  samba/

$ ls -ls /etc/h*         # sort by size, smallest first for all files starting with h in /etc/ directory
8 -rw-r--r-- 1 root root 4781 Mar 17  2016 /etc/hdparm.conf
4 -rw-r--r-- 1 root root   92 Oct 22  2015 /etc/host.conf
4 -rw-r--r-- 1 root root   12 Feb 18 01:21 /etc/hostname
4 -rw-r--r-- 1 root root  191 Feb 18 01:21 /etc/hosts
4 -rw-r--r-- 1 root root  411 Feb 18 01:29 /etc/hosts.allow
4 -rw-r--r-- 1 root root  711 Feb 18 01:29 /etc/hosts.deny
                                   

3. cat – concatenate files and print on the standard output.

cat conCATenates one or more files given as argument and prints those on the standard output (console).
If no file or ‘-‘ (dash) is given, it reads from standard input until EOF (Ctrl+D) is pressed and prints is to standard output.

$ ls -l linus         # ls to make sure file exists
-rw-rw-r-- 1 daniel daniel 403 Apr 15 01:20 linus

$ cat linus           # print content of file to stdout
Hello everybody out there using minix -

I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones.
This has been brewing since april, and is starting to get ready.
I'd like any feedback on things people like/dislike in minix,
as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things).

$ cat -n linus       # show line numbers with -n
     1	Hello everybody out there using minix -
     2	
     3	I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones.
     4	This has been brewing since april, and is starting to get ready.
     5	I'd like any feedback on things people like/dislike in minix,
     6	as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things).

$ cat          # read from stdin(keyboard) and print to stdout(screen), repeats after me until I press Ctr+D to end it.
reading
reading
from standard inpu
from standard inpu
pressing Ctr+D now
pressing Ctr+D now

$ cat << EOF > file-from-stdin       # Reads from keyboard until EOF is pressed and saves(redirects) the text to a file.
  I read this from stdin
  end of file
  EOF

$ ls -l file-from-stdin               # printing content of file we created above.
-rw-rw-r-- 1 daniel daniel 35 Apr 15 01:22 file-from-stdin

$ cat file-from-stdin 
I read this from stdin
end of file

4. clear – clears the terminal screen.

clear is self-explanatory, it clears the terminal display and places your cursor at the top left corner. Similar to “cls” command in DOS/Windows/PowerShell.

$ clear

5. rm – removes one or more files.

 ls           # list of files/dirs in current directory
demo-link  demo.txt  file-from-stdin  linus  mail  myfile  nfs  redhat  run.sh  samba

$ ls myfile    # file exists
myfile

$ rm myfile      # delete file

$ ls myfile      # we should get an error
ls: cannot access 'myfile': No such file or directory

$ rm -i linus    # prompt for confirmation before removing file
rm: remove regular file 'linus'? y

$ rm -v demo.txt   # add verbosity, explain what is being done.
removed 'demo.txt'

$ rm -d mail -v     # remove empty directory
removed directory 'mail'

$ rm redhat/         # try to delete directory with rm, should get an error
rm: cannot remove 'redhat/': Is a directory

$ rm -d redhat        # error again, not empty
rm: cannot remove 'redhat': Directory not empty

$ rm -r redhat/ -v     # use -r for recursive removal of directory and its contents.
removed 'redhat/version7'
removed 'redhat/version6'
removed directory 'redhat/'

Use rmdir to delete the named directory, not its contents. To completely wipe out a directory and its contents use ‘rm -r’.

6. mkdir – make or create one or more directories.

mkdir is used to create one or more directories under current directory if no directory argument is given. The user creating the directory must have the permission to create a directory under the specified directory.

$ whoami                  # regular user
daniel

$ mkdir /root/mydir       # trying to create directory under root user's home directory, should get permission error.
mkdir: cannot create directory ‘/root/mydir’: Permission denied

$ pwd                      # current working directory, my home directory
/home/daniel/projects

$ mkdir april-15           # create directory here
$ ls
april-15  demo-link  file-from-stdin  nfs  run.sh

$ mkdir nfs -v             # can't overwrite an existing directory
mkdir: cannot create directory ‘nfs’: File exists
$ mkdir newdir/seconddir/thriddir    # can't create a series of directories without parent directories existing
mkdir: cannot create directory ‘newdir/seconddir/thriddir’: No such file or directory

$ mkdir -p newdir/seconddir/thriddir  # -p makes parent directories as well, solves above problem.

$ ls -R newdir/                       # recursive (-R) listing with ls shows all directories created.
newdir/:
seconddir

newdir/seconddir:
thriddir

newdir/seconddir/thriddir:

7. mv – moves a file or directory to another location.

mv is most commonly used for renaming files and directories. You can specify more than two directory arguments,
it will move the all directory, except the last one to the last (destination) directory.

$ mv -v run.sh run-script.sh   # -v is for verbose, move file.
'run.sh' -> 'run-script.sh'

$ ls run*                      # file has been renamed.
run-script.sh

$ mv samba/ nfs/ redhat/ -v          # move first two directories to the last one
'samba/' -> 'redhat/samba'
'nfs/' -> 'redhat/nfs'

$ ls redhat/
nfs  samba      

8. cp – copy files and directories.

cp is used to copy files as well as directories, most commonly to take backups.

$ ls
april-15  demo  demo-link  demo.txt  file-from-stdin  hosts-backup  linus  mail  myfile  newdir  redhat  run-script.sh

$ cp demo demo-new -v    # copying directory
cp: omitting directory 'demo'

$ cp -r demo demo-new -v    # recursive(-r) copy, with verbose(-v) mode.
'demo' -> 'demo-new/demo'
'demo/one' -> 'demo-new/demo/one'

$ cp -av redhat /tmp/      # archive, preserve the specified attributes
'redhat' -> '/tmp/redhat'
'redhat/nfs' -> '/tmp/redhat/nfs'
'redhat/samba' -> '/tmp/redhat/samba'
'redhat/newdir' -> '/tmp/redhat/newdir'
'redhat/newdir/seconddir' -> '/tmp/redhat/newdir/seconddir'
'redhat/newdir/seconddir/thriddir' -> '/tmp/redhat/newdir/seconddir/thriddir'

$ls -al /tmp/redhat/
total 20
drwxrwxr-x  5 daniel daniel 4096 Apr 15 01:55 .
drwxrwxrwt 13 root   root   4096 Apr 15 01:58 ..
drwxrwxr-x  3 daniel daniel 4096 Apr 15 01:55 newdir
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:04 nfs
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:51 samba

$ touch demo/one mail/one

$ cp demo/one mail/one        # overwrite file

$ cp -i demo/one mail/one     # prompt before overwriting a file
cp: overwrite 'mail/one'? y

$ cp -s demo-link  demo-link2  # copy as symbolic link

$ ls -l
...
lrwxrwxrwx  1 daniel daniel    8 Apr 15 01:51 demo-link -> demo.txt
lrwxrwxrwx  1 daniel daniel    9 Apr 15 02:02 demo-link2 -> demo-link
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:58 demo-new
...
$ cp demo-link demo-link3     # copies target or dereferenced file, not symbolic link.

$ ls -l
...
drwxrwxr-x  2 daniel daniel 4096 Apr 15 02:00 demo
lrwxrwxrwx  1 daniel daniel    8 Apr 15 01:51 demo-link -> demo.txt
lrwxrwxrwx  1 daniel daniel    9 Apr 15 02:02 demo-link2 -> demo-link
-rw-rw-r--  1 daniel daniel   21 Apr 15 02:02 demo-link3
drwxrwxr-x  2 daniel daniel 4096 Apr 15 01:58 demo-new
-rw-rw-r--  1 daniel daniel   21 Apr 15 01:51 demo.txt
...

9. cd – change directory.

cd is actually a built-in shell command, you won’t find it in the file system as the other commands above. It is used to change working directory.
Use it with “pwd” to show your current directory.


$ pwd        # our current working directory
/home/daniel/projects
$ cd demo    # changing to demo/ directory
$ pwd
/home/daniel/projects/demo
$ cd -       # switch back to previous directory, "-" (dash) does the trick.
/home/daniel/projects
$ pwd
/home/daniel/projects
$ cd /root/   # you need permission to switch to protected directories.
-bash: cd: /root/: Permission denied

10. man – display information from the man pages.

The man command provides and interface to the on-line reference manuals. man will search through all the sections of the man pages.
If the section number is given, it will search only that section.

$ man man       # search the man  pages for information about the man command.

$ man ls          # help on ls

$ man 5 crontab   # search in section 5 of the man pages

$ man -k mkdir    # show short description of mkdir keyword.
mkdir (1)            - make directories
mkdir (2)            - create a directory
mkdirat (2)          - create a directory

Linux – top 10 memory consuming processes

*Show top 10 memory consuming processes in descending order –

[daniel@kauai demo]$  ps havx | awk ' { print $8 " " $10}' | sort -nr  |head  -10
2267936 /usr/libexec/qemu-kvm
841588 /usr/libexec/qemu-kvm
400336 /opt/google/chrome/chrome
316424 /opt/google/chrome/chrome
299740 /opt/google/chrome/chrome
45640 /usr/bin/python
43748 /usr/sbin/named-sdb
39516 /usr/bin/Xorg
31724 libvirtd
24080 /usr/libexec/mysqld


*Continuously show top 10 every one second – Use Ctrl+C to stop.

[daniel@kauai demo]$ while (true); do ps havx | awk ' { print $8 " " $10}' | sort -nr  |head  -10; echo "..... " ; sleep 1 ; done
2267936 /usr/libexec/qemu-kvm
841540 /usr/libexec/qemu-kvm
401500 /opt/google/chrome/chrome
316360 /opt/google/chrome/chrome
300060 /opt/google/chrome/chrome
45640 /usr/bin/python
43748 /usr/sbin/named-sdb
39516 /usr/bin/Xorg
31724 libvirtd
24080 /usr/libexec/mysqld

..... 
2267936 /usr/libexec/qemu-kvm
841540 /usr/libexec/qemu-kvm
401500 /opt/google/chrome/chrome
316360 /opt/google/chrome/chrome
300060 /opt/google/chrome/chrome
45640 /usr/bin/python
43748 /usr/sbin/named-sdb
39516 /usr/bin/Xorg
31724 libvirtd
24080 /usr/libexec/mysqld

..... 
2267936 /usr/libexec/qemu-kvm
841540 /usr/libexec/qemu-kvm
401516 /opt/google/chrome/chrome
316360 /opt/google/chrome/chrome
300060 /opt/google/chrome/chrome
45640 /usr/bin/python
43748 /usr/sbin/named-sdb
39516 /usr/bin/Xorg
31724 libvirtd
24080 /usr/libexec/mysqld

..... 
2267936 /usr/libexec/qemu-kvm
841540 /usr/libexec/qemu-kvm
401528 /opt/google/chrome/chrome
316360 /opt/google/chrome/chrome
300060 /opt/google/chrome/chrome
43748 /usr/sbin/named-sdb
39516 /usr/bin/Xorg
31724 libvirtd
24080 /usr/libexec/mysqld
21260 gnome-terminal

..... 
^C
[daniel@kauai demo]$ 

grep exclude grep from output

When you run a Linux command and pipe it through grep, the grep text itself is shown in the output as well. Once common technique is to use “grep -v” to exclude it. But here is a handy tip which excludes the grep text by placing the first character in a parenthesis –

Normal grep output – notice “grep ssh” is shown in the output :

[daniel@kauai tmp]$ ps aux |grep ssh
root      2795  0.0  0.0  66236  1236 ?        Ss   Mar01   0:38 /usr/sbin/sshd
daniel    6317  0.0  0.0 103320   832 pts/1    S+   23:21   0:00 grep ssh
root     25544  0.0  0.0 100016  4232 ?        Ss   22:17   0:00 sshd: daniel [priv]
daniel   25552  0.0  0.0 100016  2008 ?        S    22:17   0:00 sshd: daniel@pts/8

With the parenthesis trick we can exclude “grep ssh” from the output –

[daniel@kauai tmp]$ ps aux |grep [s]sh
root 2795 0.0 0.0 66236 1236 ? Ss Mar01 0:38 /usr/sbin/sshd
root 25544 0.0 0.0 100016 4232 ? Ss 22:17 0:00 sshd: daniel [priv]
daniel 25552 0.0 0.0 100016 2008 ? S 22:17 0:00 sshd: daniel@pts/8

[/bash]

Linux – empty or truncate files with strange names such as white space etc.

In Linux, it is very common to expect the files in the system to follow certain naming conventions – such as no white space, usually only lower cases, alphanumeric with underscore or dashes. But in some cases, you will find files which don’t follow this convention – the files might have been copied from other OSes such as Microsoft Windows or MacOS. Here is a trick to empty these files without deleting them.

Use the “truncate” command to empty files with non-standard names.

Requirement – empty files with white space in file name. Keep the files, just reduce the size to 0.

# find . -type f -exec ls -l {} \;
-rw-rw-r-- 1 nagios nagios 0 Dec 21 11:21 ./app/\var\log\messages
-rw-rw-r-- 1 nagios nagios 1359 Dec 19 06:26 ./puppet/\var\log\syslog
-rw-rw-r-- 1 nagios nagios 8071 Dec 15 02:30 ./ftp/Microsoft-Windows-EventCollector\Operational

# find . -type f -exec truncate -s 0 {} \;

# find . -type f -exec ls -l {} \;
-rw-rw-r-- 1 nagios nagios 0 Dec 21 11:27 ./app/\var\log\messages
-rw-rw-r-- 1 nagios nagios 0 Dec 21 11:27 ./puppet/\var\log\syslog
-rw-rw-r-- 1 nagios nagios 0 Dec 21 11:27 ./ftp/Microsoft-Windows-EventCollector\Operational

With the command

find . -type f -exec truncate -s 0 {} \;

, we were able to list all files in current directory and empty them.

C programming Language – Code snippets

C Programming Language, 2nd Edition

Compiling and running the sample codes using gcc :

gcc sample.c -o sample
./sample

Chapter 3 – Control Flow

1. Trim whitespace

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


int main()
{
  int n,i=0;
  char s[]="   HELLO THERE    ";
  printf("Before trim:%s\n",s);
  for(n=strlen(s)-1; n>=0; n--)
   if(s[n]!=' ' && s[n]!='\t' && s[n]!='\n') break;
  s[n+1]='\0';
  while(isspace(s[i++]));
  i=0;
  while(s[i]!='\0') s[i++];
  s[i]='\0';
  printf("After trim:%s\n",s);
  return n;
}

2. Binary search

#include<stdio.h>


int binsearch(int x, int v[], int n);

int main(int argc, char *argv[])
{
  int size=argc,found;
  int counter=0,x, v[size-2];
  x=atoi(argv[size-1]);
  if (argc<3) {printf("Usage: progname integer-list integer-to-be-searched\n"); return -1; }
  while(counter <= size-3)
  { v[counter]=atoi(argv[counter+1]);
    counter++; }
(found=binsearch(x,v,size-2))!=-1 ? printf("Found=%d\n",v[found]): printf("Not found\n");
 return 0;
}

int binsearch(int x, int v[], int n)

{
   int low, high, mid;
   low=0;
   high=n-1;
   while(low<=high)
     {
       mid=(low+high)/2;
       if(x < v[mid])  high=mid-1;
       else if (x > v[mid]) low=mid+1;
       else
         return mid;
     }
return -1;
}

3. Integer to string with argument parsing.


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define  SIZE  10

void itoa(int n, char s[]);
void reverse(char s[]);
int main(int argc, char *argv[])
 {
   char s[SIZE];
   int n;
   if(argc!=2) { printf("Usage: progrname integer\n"); return -1; }
   n=atoi(argv[1]);
   itoa(n,s);
   printf("String:%s\n",s);
   return 0;

 }

void itoa(int n, char s[])
 {
    int i, sign;
    if((sign=n)<0) n=-n;
    i=0;
    do {
         s[i++]=n%10 + '0';
       } while( (n/=10)>0);

 if (sign<0) s[i++]='-';
 s[i]='\0';
 reverse(s);
}

void reverse(char s[])
{
 int c, i, j;

  for(i=0,j=strlen(s)-1; i<j; i++,j--)
   {
        c=s[i];  s[i]=s[j];  s[j]=c;
   }
}

4. Reverse string and convert integer to string

#include<stdio.h>
#include<string.h>
#define SIZE 1000 

void reverse(char s[]);
void itoa(int n, char s[]);

int main()
{
  char s[SIZE]="HELLO WORLD!!";
  reverse(s);
  printf("%s\n",s);
  itoa(87690,s);
  printf("%s\n",s);
return 0;
}

void reverse(char s[])
{
 int c, i, j;

  for(i=0,j=strlen(s)-1; i<j; i++,j--)
   {
        c=s[i];  s[i]=s[j];  s[j]=c;
   }
}

void itoa(int n, char s[])
{
  int i, sign;
  if((sign=n)<0) n=-n;
  i=0;
      do {
           s[i++] = n%10 + '0';
         } while((n/=10)>0);
  if(sign<0) s[i++] = '-';
  s[i]='\0';
  reverse(s);
}

5. Command line argument parsing


#include<stdio.h>

int main(int argc, char *argv[])
{
  int i,counter;
  printf("Number of arguments:%d\n",argc);
  printf("Arguments character-by-character\n");
   for(counter=0;counter < argc ; counter++)
    { while(*argv[counter])
      printf("%c ",*argv[counter]++);
      printf("\n");
    }

printf("\n");
return 0;
}

6. Reverse a string

#include<stdio.h>
#include<string.h>
#define SIZE 1000 

void reverse(char s[]);

int main()
{
  char s[SIZE]="HELLO WORLD!";
  reverse(s);
  printf("%s\n",s);

return 0;
}

void reverse(char s[])
{
 int c, i, j;

  for(i=0,j=strlen(s)-1; i<j; i++,j--)
   {
        c=s[i];  s[i]=s[j];  s[j]=c;
   }
}

7. Sorting with shell sort method.


#include<stdio.h>
#define  SIZE  10
void shellsort(int v[], int n);

int main()
{
int counter;
int v[SIZE]={8,13,9,45,90,24,56,11,20,10};
shellsort(v,SIZE);
for(counter=0; counter<SIZE; counter++)
  printf("%d  ",v[counter]);
printf("\n");
return 0;
}

void shellsort(int v[], int n)
{
   int gap, i, j, temp;
   for(gap=n/2; gap>0; gap/=2)
     for(i=gap; i<n; i++)
       for(j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap)
        {
           temp=v[j];
           v[j]=v[j+gap];
           v[j+gap]=temp;
        }
}

8. using switch case


#include<stdio.h>

int main()
{
  int c, i, nwhite, nother,alpha, ndigit[10];
  nwhite=nother=alpha=0;
  for(i=0; i<10; i++) ndigit[i]=0;
  while((c=getchar())!=EOF)
  {
   switch(c)
    {
      case '0': case '1': case '2': case '3': case '4': case '5':
      case '6': case '7': case '8': case '9':
        ndigit[c-'0']++; break;
      case ' ': case '\n': case '\t': nwhite++; break;
      default:
          nother++; break;
     }
   }
printf("Digits =");
for(i=0; i<10; i++) printf(" %d", ndigit[i]);
printf(", white space =%d, other = %d\n", nwhite, nother);
return 0;
}

9. Double input – strip out non integers

#include<stdio.h>
#include<ctype.h>

#define  SIZE  10

int atoi(char s[]);

int main(int argc, char *argv[])
{
  int counter=0;
  char s[SIZE];
  if (argc!=2) {
    printf("Usage: progname integer\n");
    return 1;
  }
  while(*argv[1])  s[counter++]=(*argv[1]++);
  printf("Twice Result=%d\n",2*atoi(s));
return 0;
}
int atoi(char s[])
{
  int n, i,sign;

 for(i=0; isspace(s[i]); i++);

sign=(s[i]=='-')? -1: 1;
if(s[i] == '+' || s[i] == '-') i++;
 for(n=0; isdigit(s[i]); i++)
   n=10*n + (s[i]-'0');

return sign*n;
}

Reference –

https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628#reader_0131103628

C programming Language – Code snippets

C Programming Language, 2nd Edition

Compiling and running the sample codes using gcc :

gcc sample.c -o sample
./sample

Chapter 2 – Types, Operators and Expressions

1.Convert to lower case.

#include<stdio.h>

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

{

  while(*argv[1])
   {
     if(*argv[1] >='A' && *argv[1] <='Z') { putchar(*argv[1] + 'a' -'A'); *++argv[1]; }
     else
      {putchar(*argv[1]); *++argv[1]; }
   }

printf("\n");
return 0;
}

2. Get bits


#include<stdio.h>

unsigned getbits(unsigned x,int p, int n);

int main()

{
   int x=16;
   printf("%d\n",getbits(x,4,3));

return 0;
}

unsigned getbits(unsigned x, int p, int n)
 {
   return ( x >> (p+1-n)) & ~(~0 << n);
 }

3. Count one bits


#include<stdio.h>

int bitcount(unsigned x);
int main()

{
  unsigned short x=38;

  printf("%d has %d 1 bits\n",x,bitcount(x));
  return 0;
}

int bitcount(unsigned x)
 {
   int b;
   for(b=0; x!=0; x>>=1)
    if (x&1) b++;
  return b;
}

4. Remove character from string



#include<stdio.h>

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

{


if (argc !=3)  { printf("usage: del string char\n"); return -1;}

while(*argv[1])

{
   if(*argv[1] != *argv[2]) { putchar(*argv[1]); *++argv[1]; }
   else
   { *++argv[1]; continue; }
}
printf("\n");
return 0;

}

5. Convert x to binary


#include<stdio.h>
#define  LEN 16
int main()

{
  int x=112,counter=0;
  int binary[LEN]={0};
  while(x)
   {
     binary[counter]=x%2; x/=2; counter++;
   }
while(counter>=0) { printf("%d",binary[counter]); counter--; }
printf("\n");
return 0;
}

6. Convert char to integer

#include<stdio.h>

#define NUM 1

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

{
 int counter=1,n=0;

 if(argc!=2) { printf("usage: atoi arglist\n"); return -1;}

 while(*argv[NUM])
   {
      if(*argv[NUM]>='0' && *argv[NUM]<='9') { n=10*n+(*argv[NUM]-'0'); *++argv[NUM]; }
      else
       { *++argv[NUM]; continue; }
   }
 printf("number=%d\n",n);
 return 0;

 }

Reference –

https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628#reader_0131103628

Linux – fast file system search with locate and updatedb

Typically

find

command is the most commonly used search utility in Linux. GNU find searches the directory tree rooted at each given starting-point by evaluating the given expression from left to right, according to the rules of precedence.

There is an alternative and fast way of searching for files and directories in Linux though and that is the

locate

command, and it goes hand in had with the

updatedb

utility which keeps an indexed database of the files in your system. The locate tools simply reads the database created by updatedb.

Installation –

sudo apt-get -y install mlocate           [Debian/Ubuntu]
sudo yum -y install mlocate               [CentOS/Redhat]

updatedb is usually has a daily cron job to update the default database(‘/var/lib/mlocate/mlocate.db’). To manually update the database, you can manually run the ‘updatedb’ command first. That will take a while depending on the number of files you have on your system, the last time updatedb ran or other file related changes.

First time – update the default database, run any of the below command depending on your requirements. Most likely, the first and/or third command is what you need.

updatedb
updatedb -U /some/path      # if interested in indexing specific directory that you will search frequently.
updatedb -v                 # verbose mode

Time to search
locate command is the utility to search for entries in a mlocate database.

Some examples –

locate cron         # any file or directory with cron in its name
locate -i cron      # case insensitive
locate -c cron      # only print number of found entries
locate -r 'cron$'   # regex - only files or directories with names ending in cron.
locate -r '/usr/.*ipaddress.*whl$'   # regex for eg. /usr/share/python-wheels/ipaddress-0.0.0-py2.py3-none-any.whl

locate can also print the statistics on count of files, directories, size used by updatedb default directory.

root@cloudclient:/tmp# locate -S
Database /var/lib/mlocate/mlocate.db:
	28,339 directories
	185,661 files
	11,616,040 bytes in file names
	4,481,938 bytes used to store database

Customizing updatedb
updatedb can be customized to output the search database to a different file than the default db, in addition to this we can change the directory to index other than the default root tree. We can then tell locate to use the custom db.

In the below example, I am indexing the files under home directory in /tmp/home.db database, and then run locate to use this custom DB. As you can see the number of files and directories is way lower and thus the search much faster although since it has to scan specific directory.

$ updatedb -U ~ -o /tmp/home.db
$ locate -d /tmp/home.db cron
$ locate -d /tmp/home.db -S
Database /tmp/home.db:
	3,530 directories
	29,943 files
	2,635,675 bytes in file names
	762,621 bytes used to store database

References –

https://linux.die.net/man/8/updatedb

https://linux.die.net/man/1/locate

C programming Language – Code snippets

C Programming Language, 2nd Edition

Compiling and running the sample codes using gcc :

gcc sample.c -o sample
./sample

Chapter 1 – Introductory tutorial : Input/output, characters, strings

0. Hello World!

#include<stdio.h>

int main()

{

  printf("Hello World\n");
  return 0;
}

1. Word counter


/* word counter */
#include<stdio.h>

#define  IN 1  //inside a word
#define  OUT   0  //outside a word

int main()

{
  int c,nl,nw,nc,state;
  state=OUT;
  nl=nw=nc=0;

  while((c=getchar())!=EOF)
   {
      ++nc;
      if(c=='\n') ++nl;
      if (c==' ' || c == '\n' || c=='\t') state=OUT;
      else if (state==OUT)
         {
           state=IN;
           ++nw;
          }
        }
      printf("lines=%d words=%d characters=%d\n",nl,nw,nc);
 return 0;
}

2. Convert Fahrenheit to Celsius


#include<stdio.h>

#define  LOWER 0
#define  UPPER 300
#define  STEP  20

int main()

  {
     int fahr;
     for (fahr = LOWER; fahr <= UPPER; fahr=fahr + STEP)
         printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
     return 0;
 }


3. Count characters


/* character counter */
#include<stdio.h>

int main()

{
   short int nc;
   for(nc=0; getchar()!=EOF ; ++nc);
   printf("%d\n",nc);
   return 0;
}

4. Count characters by type – digits, white spaces etc.


/* count digits, white space, others */
#include<stdio.h>

int main()
 {
   int c,i,nwhite,nother;
   int ndigit[10];

   nwhite=nother=0;
   for(i=0; i < 10; ++i)  ndigit[i]=0;

   while((c=getchar())!=EOF)
     if(c>='0' && c<='9') ++ndigit[c-'0'];
     else if (c==' ' || c=='\n' || c=='\t') ++nwhite;
     else  ++nother;

   printf("digits=");
   for(i=0;i<10;++i) printf(" %d",ndigit[i]);
   printf(",white space=%d, other=%d\n",nwhite,nother);

return 0;
}

5. Copy input to output terminal


/* copy input to output 1 */
#include<stdio.h>

int main()

{
   int c;
   c = getchar();
   while ( c!=EOF)
     {
       putchar(c);
       c = getchar();
     }
 return 0;
}

6. Copy input to output terminal (shorter version)

/* copy input to output */
#include<stdio.h>

int main()
{
   int c;
   while((c=getchar())!=EOF)
     putchar(c);
   return 0;
}

7. Print longest line


#include<stdio.h>

#define  MAXLINE  1000  /* maximum input line length */

int getline(char line[], int maxline);
void copy(char to[], char from[]);

/* print the longest input line */

int main()

{
  int len;  /* current line length */
  int max;  /* maximum length seen so far */
  char line[MAXLINE];   /* current input line */
  char longest[MAXLINE];   /*longest line saved here */

  max=0;
  while((len=getline(line,MAXLINE))>0)
    if(len>max)
       { max=len;
         copy(longest,line);
       }
 if(max>0)  /*there was a line*/
  printf("Longest Line from input is:\n%s\n",longest);
  printf("Line length is: %d characters\n",max);

return 0;
}


/*getline: read a line into s, return length */

int getline(char s[], int lim)
{
  int c,i;
  for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
   s[i]=c;
 if(c=='\n') {
  s[i]=c;
  ++i;
  }
 s[i]='\0';
 return i;
}

/*copy: copy 'from' into 'to'; assume 'to' is big enough */

void copy(char to[], char from[])
{
  int i;
  i=0;
  while((to[i]=from[i]) != '\0')
    ++i;
}

8. Print longest line – improved


#include<stdio.h>

#define  MAXLINE  1000  /* maximum input line length */

int max;
char line[MAXLINE];
char longest[MAXLINE];

int getline(char line[], int maxline);
void copy(char to[], char from[]);

/* print the longest input line */

int main()

{
  int len;  /* current line length */
  extern int max; /* maximum length seen so far */
  extern char longest[MAXLINE];  /*longest line saved here */

  max=0;
  while((len=getline(line,MAXLINE))>0)
    if(len>max)
       { max=len;
         copy(longest,line);
       }
 if(max>0)  /*there was a line*/
  printf("Longest Line from input is:\n%s\n",longest);
  printf("Line length is: %d characters\n",max);

return 0;
}


/*getline: read a line into s, return length */

int getline(char s[], int lim)
{
  int c,i;
  extern char line[];
  for(i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
   s[i]=c;
 if(c=='\n') {
  s[i]=c;
  ++i;
  }
 s[i]='\0';
 return i;
}

/*copy: copy 'from' into 'to'; assume 'to' is big enough */

void copy(char to[], char from[])
{
  int i;
  extern char line[], longest[];
  i=0;
  while((to[i]=from[i]) != '\0')
    ++i;
}

9. Power function


#include<stdio.h>

int power(int m, int n);

/* test power function */

int main()

{
  int i;
  for(i=0; i<10; ++i)
   printf("%d %d %d\n",i,power(2,i),power(-3,i));
 return 0;
}

int power(int base, int n)
 {
   int i,p=1;
   for(i=1;i<=n;++i)
     p*=base;
   return p;
 }

10. Reverse string


#include<stdio.h>

#define  MAXLINE  1000

int size=0;
void reverse(char line[], int lim);
int main()

{ extern int size;
  char line[MAXLINE];
  reverse(line,MAXLINE);
  while(size) putchar(line[--size]);
  printf("\n");
  return 0;
}

void reverse(char line[], int lim)

{
 extern int size;
 int c;
 while((c=getchar())!=EOF ) line[size++]=c;
 line[size]='\0';

}

11. Get digits only


#include<stdio.h>

int atoi(char s[]);

int main()

{
  char str[]="12a4c5 ";
  int i=0,n=0;

 while(str[i]!='\0')
   {
      if(str[i]>='0' && str[i]<='9') { n=10*n+(str[i]-'0'); i++; }
      else
       { i++; continue; }
   }
 printf("number=%d\n",n);
 return 0;

 }

12. Fahrenheit to Celsius table

/* print Fahrenheit-Celsius table for fahr =0,20,40,....,300 */

#include<stdio.h>

int main()

{
  int fahr, celsius;
  int lower, upper, step;
  lower = 0;
  upper = 300;
  step = 20;

  fahr = lower;
  while( fahr <= upper)
   {
      celsius = 5 * (fahr - 32) / 9;
      printf("%d\t%d\n", fahr, celsius);
      fahr = fahr + step;
   }

return 0;
}

Reference –

https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628#reader_0131103628