Chapter P3. The C Library (libc) functions

 
Goals for this chapter:
  • gcc (gcc)
  • glibc
    • glibc-devel
    • glibc-profile
    • glibc-common
    • nscd
  • strip (binutils)
  • touch (fileutils)
  • libstdc++
    • libstdc++-devel (/usr/include/g++-3)
 

It was new. It was singular.
It was simple. It must succeed!
-H. Nelson.


In this chapter we will the standard C Library, "libc.a" and show ho to use it. However, is fundamental to know and understand the C compiler, as a development tool, as well how is adopted by the diferent Linux distro, to avoid strange results.

We also will introduce how to use 'others' common development tools like "nm", "strings", "objdump", "objcopy", "strip", "size".

The C Language haves its Standard C Library, called "libc.a", where are located the most used function for string, Basic I/O, Mathematical and other similar essential tasks.

The libc.a interact with the following include includes files: stdio.h, string.h, math.h, stdlib.h, unistd.h, signal.h, pwd.h, sys/stat.h. and others includes files  present in  "/usr/include". Here we cover how to use these function is our programs.
 

The C Compiler


To be a programmer you need to have the ideas and projects, knows the language and the libraries that you will use. A clear knowledge about all development tools is also necessary.

From the first days of OpenSource (1989), Richard Stallman and its Free Software Foundation offers at no cost the most incredible and better compiler ever written. The 'GCC', the GNU C Compiler.

Actually the tarball (the downloadable version in tar format) is available at: ftp://gcc.gnu.org/

(Click to enlarge)

The GCC Website is http://gcc.gnu.org/.

The C Compiler is one of the most fundamental component in any Operating System, specially in Linux OS. Almost everything is compiled with the gcc or the C++ companion: "g++". All the Basic Utilities, "awk", "sed" and others are written in C. The X Window System and almost all the Windows Managers including the OpenMotif GUI is written in C. Also, Gtk is written in C. Modern interfaces as Qt and KDE are written in C++.

For this reason is fundamental to know and understand very well, how to use C functions.
 

The RedHat 2.96 'gaffe' compiler


After the RedHat Cygnus acquisition, RedHat start to develop its own C Compiler, "2.96". As explains Mark Mitchell, GCC Release Manager the release of this version (not in accord with GNU GCC numbers) was a real problem, also because the generated binaries from C++ code, are not compatible with its equivalent GNU compilers.

The RPM packages for the GCC Compiler in 7.2 are the following:

[root@ftosx1 RPMS]# ls -al gcc-*
-rw-r--r--    2 root     root      2987778 Sep  7 18:06 gcc-2.96-98.i386.rpm
-rw-r--r--    2 root     root      1730815 Sep  7 18:06 gcc-c++-2.96-98.i386.rpm
-rw-r--r--    2 root     root      1303223 Sep  7 18:06 gcc-chill-2.96-98.i386.rpm
-rw-r--r--    2 root     root      1758083 Sep  7 18:06 gcc-g77-2.96-98.i386.rpm
-rw-r--r--    2 root     root      1333136 Sep  7 18:06 gcc-java-2.96-98.i386.rpm
-rw-r--r--    2 root     root      1208700 Sep  7 18:06 gcc-objc-2.96-98.i386.rpm
[root@ftosx1 RPMS]#

Also is included the C Pre-Processor: "cpp"

[root@ftosx1 RPMS]# ls -al cpp*
-rw-r--r--    3 root     root       194154 Sep  7 18:06 cpp-2.96-98.i386.rpm

and also the libstdc++*, the  GNU Standard C++ an ongoing project to implement the ISO 14882 Standard C++ library.

[root@ftosx1 RPMS]# ls -al libstdc++*
-rw-r--r--    3 root     root       164400 Sep  7 18:06 libstdc++-2.96-98.i386.rpm
-rw-r--r--    2 root     root       357742 Sep  7 18:06 libstdc++-devel-2.96-98.i386.rpm

Therefore from the gcc-X.src are build 9 packages that regards the GNU Compilers; the C Lib belong to the "glibc" RPM Package, we will back on this later in this chapter. Both, the "GCC" and GLIBC and the LIBSTDC++ are the three components necessary to develop programs in C and C++, on Linux systems.

Now, is very important to remark that the 2.96.X Compiler is not a GNU project but a RedHat 'gaffe' compiler.

This compiler is a 'gaffe' for the following reasons:

More than a technical 'gaffe' seems to be a clear 'un-documented' mode to stay far and indipendent from others distro. This behaviour causes only problems, not only to RedHat but to the entire Linux community.

What is the sense to create a 'different' compiler with new parameters while 'everyone' uses the acepted standard gcc with its 'standard' parameters ?

Other distro adopt the standard GNU C Compiler releases ... and follows the normal trend. For example, we have:

Also, the Linux kernel maintainers, prevent problems in the README

" - Make sure you have gcc 2.95.3 available.  gcc 2.91.66 (egcs-1.1.2) may
   also work but is not as safe, and *gcc 2.7.2.3 is no longer supported*.
   Also remember to upgrade your binutils package (for as/ld/nm and company)
   if necessary. For more information, refer to ./Documentation/Changes.

What is the better choice for 'old' RedHat users to maintain compatibility with the latest version. FTOSX 2002, adopt the GNU GCC 3.1.

However, adopt and use the RedHat "glibc" open a compatibity for common RedHat/Cygnus. In other words, not the compiler but, yes for the glibc compiler. Other discussion in this sense will simply make a final decision for one or other distro.
 

The GCC GNU 3.1

Why GNU GCC 3.1 compiler is so important ?

With the release of GNU GCC 3.1, the GCC team, complete an important taks in GCC history with a complete C++ ABI implementation.

In fact, as explained in the LSB 1.1, the C++ is immature and therefore does not belong to the LSB.

The immaturity regards the ABI (Application Binary Interface), for C++. This ABI does not have a  clear form. The information about this matter is available at:

This company: codesourcey haves the role to certify and test the GNU GCC Compiler.

Because neither GCC 3.1 is 100% complaint, in LSB 1.2, the Mapping continues to be immature. However, GNU C++ 3.1 open the trend to solve this matter. The GNU GCC 3.1 makes a difference between past and new innovations.

The previous "chil" support had been removed. Actually the GNU GCC 3.1, supports: C, C++, Fortran, Java and Ada languages.

Here we list the RPM packages:

The C Pre-Processor.


One of the first steps that a C Compiler follows to generate a binary from the C source (written in Plain ASCII), is the pre-processor.

The preprocessor, the 'cpp' evaluate and explode all the #includes and #define.

Consider the following source:

[root@ftosx1 Chap3]# more stat.c
 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MIN_ARGUMENTS 2

main (int argc, char ** argv)
{
        int i;
        struct stat mybuf;

        if (argc < 2)
                fprintf (stderr, "Use: %sfile(s)\n", argv[0]);
        else
          for ( i = 1; i < argc; ++i)
           if (stat (argv[1], &mybuf))
                                fprintf (stderr, "%s: can't stat %s\n", argv[0], argv[1]);
           else
                                printf ("%03o\t%s\n",  (long) (mybuf.st_mode & 0xffff) , argv[i]);
}

[root@ftosx1 Chap3]#

Note the lines #include and #define.

As introduced in the previous Chapter, the #define represent a macro that may be a function or a number, while the include is a set of declarations.

The 'cpp' expand all these defines and includes in a very large source with all the expansions.

[root@ftosx1 Chap3]# cpp stat.c > stat.cpp
[root@ftosx1 Chap3]# head !$
head stat.cpp
# 1 "stat.c"
 

# 1 "/usr/include/stdio.h" 1 3

...

The expanded source have a size equivalent to more than 20 times the original ".c" source. Please note,

-rw-r--r--    1 root     root          443 Mar  4 10:17 stat.c
-rw-r--r--    1 root     root        27216 Mar  4 10:27 stat.cpp

In this case the size of the expanded source is 61 time the original C.

The "cpp" includes some options to includes also comments in the define explosion

For example we have:

    -C: Do not discard comments

    -P:  Inhibit generation of #-lines

and

    -traditional: to imitate the old C
 

The C Library: "libc.a"


In the same mode that the RPM Packages includes the compiler, the C Library belong to another package: "glibc".

In fact, running the command:

[root@ftosx1 root]# rpm -qf /usr/lib/libc.a
glibc-devel-2.2.90-8
[root@ftosx1 root]#

We note that the library belong to the glibc-devel. The complete set of packages generated from the "glibc.X.src" is the following:

A library is a 'simple' set ob objects. Runing the command: "nm" we can list all the objects present in the library, in particular now for the libc.a.

[root@ftosx1 root]# nm /usr/lib/libc.a | more

init-first.o:
000001a3 t Letext
         U __close
         U __environ
         U __fpu_control
         U __init_misc
00000004 C __libc_argc
00000004 C __libc_argv
         U __libc_fatal
0000017c T __libc_init_first
...

For example, we can list all the 'printf' functions:

[root@ftosx1 root]# nm /usr/lib/libc.a | grep printf.o
vfprintf.o:
vprintf.o:
reg-printf.o:
fprintf.o:
printf.o:
snprintf.o:
sprintf.o:
asprintf.o:
dprintf.o:
vfwprintf.o:
iosprintf.o:
iovsprintf.o:
fwprintf.o:
swprintf.o:
vwprintf.o:
wprintf.o:
vswprintf.o:
vasprintf.o:
iovdprintf.o:
vsnprintf.o:
obprintf.o:
[root@ftosx1 root]#

Now, we have a better clear vision about the compiler and its components, we will move to the programming part.

Some C Library Functions


We will introduce the C Library functions in accord to its role, organized in by includes.

In order of importance we can list the following includes.

Of course there are others functions and other includes files all present in the tree which root directory is "/usr/include"

The stdio functions

The stdio.h file is one of the most importants include files. The name stdio, stand for Standard I/O (I/O stand for Input Output) functions.

Therefore, functions to handle files, or to print data on files are present here.

We have a quick list.

For example, this includes file list the normal size for buffers, when we need to open a file and read it in blocks (using a buffer).

Please compile the source:

[root@ftosx1 Chap3]# more buffsiz.c

#include <stdio.h>

main()
{
        printf ("%d\n", BUFSIZ);
}
[root@ftosx1 Chap3]#

And the BUFSIZ is:

[root@ftosx1 Chap3]# ./buffsiz
8192
[root@ftosx1 Chap3]#

A normal mode to use these functions is the following.

#include <stdio.h>

main(argc, argv)
int argc;
char **argv;
{
    int c;
    FILE *from, *to;

    /*
     * Check our arguments.
     */
    if (argc != 3) {
        fprintf(stderr, "Usage: %s from-file to-file\n", *argv);
        exit(1);
    }

    /*
     * Open the from-file for reading.
     */
    if ((from = fopen(argv[1], "r")) == NULL) {
        perror(argv[1]);
        exit(1);
    }

    /*
     * Open the to-file for appending.  If to-file does
     * not exist, fopen will create it.
     */
    if ((to = fopen(argv[2], "a")) == NULL) {
        perror(argv[2]);
        exit(1);
    }

    /*
     * Now read characters from from-file until we
     * hit end-of-file, and put them onto to-file.
     */
    while ((c = getc(from)) != EOF)
        putc(c, to);

    /*
     * Now close the files.
     */
    fclose(from);
    fclose(to);
    exit(0);
}
[root@ftosx1 My]#

To compile this program we need to run the command:

[root@ftosx1 My]# gcc 2.1.c -o mycopy

Note that nothing else is necessary. Neither special includes flags like "-I" (to add new includes), neither "-L/usr/lib/" (to add more libraries) are needed.

Note also the "-o" that is the flag to compile the program and generate the binary.

To run this binary that does a simple copy we run the command:

[root@ftosx1 My]# ./mycopy /etc/passwd ./mypasswd
[root@ftosx1 My]# diff /etc/passwd ./mypasswd
[root@ftosx1 My]#

Note that we add the "." before the binary because (generally) it does not belong to the PATH enviroment.

In the program we apply a very elementary approach.

The type FILE.

In the previous example
 

[root@ftosx1 Chap3]# more sizeof_file.c

#include <stdio.h>

main ()
{
        FILE * myfile;

        printf ("%d\n", sizeof (myfile));

}
[root@ftosx1 Chap3]#

Compiling this source we will get the following output.

[root@ftosx1 Chap3]# gcc sizeof_file.c -o sizeof_file
[root@ftosx1 Chap3]# ./sizeof_file
4
[root@ftosx1 Chap3]#

Therefore the sizeof of the FILE type is 4 bytes.

The FILE type is one of the common structures in C language. While the FILE type is defined with a typedef in its stdio.h:

typedef struct _IO_FILE FILE;

we will have the definition inside the file "/usr/include/libio.h"

struct _IO_FILE {
  int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */

  struct _IO_marker *_markers;

  struct _IO_FILE *_chain;

  int _fileno;
  int _blksize;
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];

  /*  char* _save_gptr;  char* _save_egptr; */

  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

Is very normal that a "#includes" file includes other #include files. The reason for this is for semplicity ... so we the programer ... need to include a single "include" file: "#include <stdio.h>"

The FILE type is also used for directories.

We list here a small sample about that.
 

[root@ftosx1 My]# more 4.1.c

#include <sys/types.h>
#include <sys/dir.h>
#include <stdio.h>

main()
{
    FILE *fp;
    struct direct dir;
    int n;

    if ((fp = fopen(".", "r")) == NULL) {
        perror("current directory");
        exit(1);
    }

        /*
         * Read directory entries.  Since we're reading
         * entries one at a time, we use the fread routine,
         * which buffers them internally.  Don't use the
         * low-level read to do things this way, since
         * reading very small quantities of data (16 bytes)
         * at a time is very inefficient.
         */
    while ((n = fread(&dir, sizeof(dir), 1, fp)) > 0) {
        /*
         * Skip removed files.
         */
        if (dir.d_ino == 0)
            continue;

        /*
         * Make sure we print no more than ... 30
         * characters.
         */
        printf("%.*s\n", 30, dir.d_name);
    }

    fclose(fp);
    exit(0);
}

[root@ftosx1 My]#
 

The C types: sys/stat.h

However, the FILE type does not regards the file as we know, supporting the UID, GID as well the size and other similar info.

[root@ftosx1 root]# ls -al /etc/passwd
-rw-r--r--    1 root     root         1666 Jul  4 15:23 /etc/passwd
[root@ftosx1 root]#

The C structure for this is the stat structure.

struct stat
  {
    __dev_t st_dev;         /* Device.  */
    unsigned short int __pad1;
#ifndef __USE_FILE_OFFSET64
    __ino_t st_ino;         /* File serial number.  */
#else
    __ino_t __st_ino;           /* 32bit file serial number.    */
#endif
    __mode_t st_mode;           /* File mode.  */
    __nlink_t st_nlink;         /* Link count.  */
    __uid_t st_uid;         /* User ID of the file's owner. */
    __gid_t st_gid;         /* Group ID of the file's group.*/
    __dev_t st_rdev;            /* Device number, if device.  */
    unsigned short int __pad2;
#ifndef __USE_FILE_OFFSET64
    __off_t st_size;            /* Size of file, in bytes.  */
#else
    __off64_t st_size;          /* Size of file, in bytes.  */
#endif
    __blksize_t st_blksize;     /* Optimal block size for I/O.  */

#ifndef __USE_FILE_OFFSET64
    __blkcnt_t st_blocks;       /* Number 512-byte blocks allocated. */
#else
    __blkcnt64_t st_blocks;     /* Number 512-byte blocks allocated. */
#endif
    __time_t st_atime;          /* Time of last access.  */
    unsigned long int __unused1;
    __time_t st_mtime;          /* Time of last modification.  */
    unsigned long int __unused2;
    __time_t st_ctime;          /* Time of last status change.  */
    unsigned long int __unused3;
#ifndef __USE_FILE_OFFSET64
    unsigned long int __unused4;
    unsigned long int __unused5;
#else
    __ino64_t st_ino;           /* File serial number.  */
#endif
  };

Notet that here are listed the size (st_size), as well the inode (st_ino).

A smart user may ask, what are "__ino_t" types? These types are the type used by

May be that this type is a complex "define" using standard types, or a struct or a simple typedef.

In this case is a simple typedef for __u_long that is equivalent to unsigned long.

types.h:typedef __u_long __ino_t;               /* Type of file serial numbers.  */
 

However, may happen almost everyting. Note for example the use of "ifndef" inside the simple structure declaration. This is the standard mode to use the code (C or C++).

Now, we will write a simple program that will list the size and inode info for the local files.

[root@ftosx1 Chap3]# more stat.c
 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MIN_ARGUMENTS 2

main (int argc, char ** argv)
{
        int i;
        struct stat mybuf;

        if (argc < MIN_ARGUMENTS )
                fprintf (stderr, "Use: %s file(s)\n", argv[0]);
        else
                for ( i = 1; i < argc; ++i)
                        if (stat (argv[1], &mybuf))
                                fprintf (stderr, "%s: can't stat %s\n", argv[0], argv[1]);
                        else
                                printf ("%d\t%03o\t%s\n",  (long) (mybuf.st_ino), (long) (mybuf.st_mode & 0xffff) , argv[i]);
}

[root@ftosx1 Chap3]#

We will run the commands to compile.

[root@ftosx1 Chap3]# gcc stat.c -o stat

To get the info we will check before with our "ls" (listing programs) and add the parameter for inode.

[root@ftosx1 Chap3]# ls -ali stat.c
 239985 -rw-r--r--    1 root     root          470 Jul  5 13:20 stat.c
[root@ftosx1 Chap3]#
[root@ftosx1 Chap3]# ./stat stat.c
239985  100644  stat.c
[root@ftosx1 Chap3]#

Note that the file size is the same while the mode is 644. The number '1' means archive.

We can also apply this to the directory:

[root@ftosx1 Chap3]# ./stat ..
239919  40755   ..
[root@ftosx1 Chap3]#

The number '4' means directory. The 0755 are the actual properties for this directory.

Other info will be available in the same mode.

The pwd functions

There are another important info that regards the "/etc/passwd" file.

The information for the "/etc/passwd" file is handled by the includes file "pwd.h"; not Print Working Directory.

The structure is the following.

/* The passwd structure.  */
struct passwd
{
  char *pw_name;        /* Username.  */
  char *pw_passwd;      /* Password.  */
  __uid_t pw_uid;       /* User ID.  */
  __gid_t pw_gid;       /* Group ID.  */
  char *pw_gecos;       /* Real name.  */
  char *pw_dir;         /* Home directory.  */
  char *pw_shell;       /* Shell program.  */
};

Now, we will the standard C function getpwnam to browse the entire passwd entry.

Our first program read the information for the user "root".

#include <stdio.h>
#include <pwd.h>

#define NAMELEN 8

main()
{
    FILE *fp;
    struct passwd *p;
    char tmp[NAMELEN+1];
    struct passwd *getpwnam();

    strcpy(tmp, "root");

    if ((p = getpwnam(tmp)) == NULL)
        exit (1);

    printf("%-30.30s %s %d %d %s %s %s\n", p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);

    exit(0);
}

Compiling ...

[root@ftosx1 My]# gcc mypasswd.c -o mypasswd

Before to run we will list the "root" entry.

[root@ftosx1 My]# more /etc/passwd | grep root:x
root:x:0:0:root:/root:/bin/bash
[root@ftosx1 My]#

Now, we will print the results

[root@ftosx1 My]# ./mypasswd
root                           x 0 0 root /root /bin/bash
[root@ftosx1 My]#

We can update the program using the function:

#include <stdio.h>
#include <pwd.h>

#define NAMELEN 8

main()
{
    FILE *fp;
    struct passwd *p;
    char tmp[NAMELEN+1];
    struct passwd *getpwnam();
    char *username, *getlogin();

    /*
     * Get the user's name.
     */
    if ((username = getlogin()) == NULL) {
        fprintf(stderr, "Who are you?\n");
        exit(1);
    }

    strncpy(tmp, username, NAMELEN);

    if ((p = getpwnam(tmp)) == NULL)
        exit (1);

    printf("%-30.30s %s %d %d %s %s %s\n", p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);

    exit(0);
}

This function gets the user using the program, and apply the getpwnam routine.

[root@ftosx1 My]# ./mypasswd2
root                           x 0 0 root /root /bin/bash
[root@ftosx1 My]#

The string functions

While in C++ language append strings is very elementary and equivalent to add numbers, in C there are a complete set of function to works with strings.

We have:

For example, in Obfuscated C and Other Mysteries, Don Libes (the Expect inventor), develop a complex function for strlen.

bool n(void* s) {
    return ((*(long*)s-0x01010101)&~(*(long*)s)&0x80808080);
}

int f(char* p) {
       int r = 0;
       while(!n(p))r+=4,p+=4;
       while(*p++)++r;
       return r;
}

Now, we will develop some special examples to use this functions:

The use of these function is quite simple or elementary.

For example, in the previous program we use the
 

   char tmp[NAMELEN+1];

   strncpy(tmp, username, NAMELEN);

Where username return from a function and is a char pointer. There are no secrets at all. However is important to remember that a string may be understood as vector of characters, that must have a well know end.

To end a string is sufficient to add a char NULL, '\0'.

That's all. If you try to use a memoey position out of the range, for example the string is long 45 characters, and you try to write (also to access) a position like 76, the program will stop and generate a SEGV.

Here we will introduce a pretty and simple example about strtok, that is probably the most not common function. The other functions are very easy to use.

The example is quit simple.

We have a string ... and will split in tokens using an allocated char *.

[root@ftosx1 Chap3]# more strtok.c

#include <stdio.h>
#include <malloc.h>

main ()
{

        char line[50], * tmp;

        strcpy (line, "John Smith     :1620 26th Street - Santa Monica:4257:1:18:M");

        puts (line);

        strtok (line, ":");
        puts (line);

        tmp = calloc (50, sizeof(char));

        tmp = (char *) strtok (NULL, ":");
        puts (tmp);

        tmp = (char *) strtok (NULL, ":");
        puts (tmp);

        tmp = (char *) strtok (NULL, ":");
        puts (tmp);

        tmp = (char *) strtok (NULL, ":");
        puts (tmp);
 

}

[root@ftosx1 Chap3]#

Compiling and executing we will have:

[root@ftosx1 Chap3]# gcc strtok.c -o strtok
[root@ftosx1 Chap3]#
[root@ftosx1 Chap3]# ./strtok
John Smith     :1620 26th Street - Santa Monica:4257:1:18:M
John Smith
1620 26th Street - Santa Monica
4257
1
18
[root@ftosx1 Chap3]#
 

The math functions

The C library also includes a complete for mathematica functions:

We list here these functions:

Check Chapter 1 for examples on "bc" program.

The stdlib functions

The stdlib functions regards the transformation between types, . While in C is very normal changes or transform type this don't happens in C++.

We list here the functions:

Note the last functions: abs, labs, div, ldiv. These functions handle the divisions between integers.

Example about this functions are real elementary and will no comment here. However, we prefer to introduce the includes <stdarg.h>. In this file are included the declaration.

va_list argument_list;

This is the mode used by functions like printf, scanf, and others to handle a large list of arguments, basically unlimited, or un-know.

The signals

Here we simply introduce the UNIX/Linux signal. Basically, we can send signals to programs to kill them, to stop them, etc.

Signals are a very important matter on UNIX system, and working with sleep and shell programming.

Here we will simply list the signals.

The signals are the following:

/* Signals.  */
#define SIGHUP          1       /* Hangup (POSIX).  */
#define SIGINT          2       /* Interrupt (ANSI).  */
#define SIGQUIT         3       /* Quit (POSIX).  */
#define SIGILL          4       /* Illegal instruction (ANSI).  */
#define SIGTRAP         5       /* Trace trap (POSIX).  */
#define SIGABRT         6       /* Abort (ANSI).  */
#define SIGIOT          6       /* IOT trap (4.2 BSD).  */
#define SIGBUS          7       /* BUS error (4.2 BSD).  */
#define SIGFPE          8       /* Floating-point exception (ANSI).  */
#define SIGKILL         9       /* Kill, unblockable (POSIX).  */
#define SIGUSR1         10      /* User-defined signal 1 (POSIX).  */
#define SIGSEGV         11      /* Segmentation violation (ANSI).  */
#define SIGUSR2         12      /* User-defined signal 2 (POSIX). */
#define SIGPIPE         13      /* Broken pipe (POSIX).  */
#define SIGALRM         14      /* Alarm clock (POSIX).  */
#define SIGTERM         15      /* Termination (ANSI).  */
#define SIGSTKFLT       16      /* Stack fault.  */
#define SIGCLD          SIGCHLD /* Same as SIGCHLD (System V).  */
#define SIGCHLD         17      /* Child status has changed (POSIX).  */
#define SIGCONT         18      /* Continue (POSIX).  */
#define SIGSTOP         19      /* Stop, unblockable (POSIX).  */
#define SIGTSTP         20      /* Keyboard stop (POSIX).  */
#define SIGTTIN         21      /* Background read from tty (POSIX).  */
#define SIGTTOU         22      /* Background write to tty (POSIX).  */
#define SIGURG          23      /* Urgent condition on socket (4.2 BSD).  */
#define SIGXCPU         24      /* CPU limit exceeded (4.2 BSD).  */
#define SIGXFSZ         25      /* File size limit exceeded (4.2 BSD).  */
#define SIGVTALRM       26      /* Virtual alarm clock (4.2 BSD).  */
#define SIGPROF         27      /* Profiling alarm clock (4.2 BSD).  */
#define SIGWINCH        28      /* Window size change (4.3 BSD, Sun).  */
#define SIGPOLL         SIGIO   /* Pollable event occurred (System V).  */
#define SIGIO           29      /* I/O now possible (4.2 BSD).  */
#define SIGPWR          30      /* Power failure restart (System V).  */
#define SIGSYS          31      /* Bad system call.  */
#define SIGUNUSED       31

A complete coverage is offered in Chapter P8. Process management
 

The time functions

To complete the C Library introduction we will introduce the time structure and use it.

The tm function is included in the file: time.h

struct tm
{
  int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
  int tm_min;                   /* Minutes.     [0-59] */
  int tm_hour;                  /* Hours.       [0-23] */
  int tm_mday;                  /* Day.         [1-31] */
  int tm_mon;                   /* Month.       [0-11] */
  int tm_year;                  /* Year - 1900.  */
  int tm_wday;                  /* Day of week. [0-6] */
  int tm_yday;                  /* Days in year.[0-365] */
  int tm_isdst;                 /* DST.         [-1/0/1]*/

# ifdef __USE_BSD
  long int tm_gmtoff;           /* Seconds east of UTC.  */
  __const char *tm_zone;        /* Timezone abbreviation.  */
# else
  long int __tm_gmtoff;         /* Seconds east of UTC.  */
  __const char *__tm_zone;      /* Timezone abbreviation.  */
# endif
};

Now we will run a program that do a countdown using the time function.

[root@ftosx1 My]# more 5.3.c
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>

main()
{
    int n, nfds;
    char buf[32];
    fd_set readfds;
    struct timeval tv;

    /*
     * We will be reading from standard input (file
     * descriptor 0), so we want to know when the
     * user has typed something.
     */
    FD_ZERO(&readfds);
    FD_SET(0, &readfds);

    /*
     * Set the timeout for 15 seconds.
     */
    tv.tv_sec = 15;
    tv.tv_usec = 0;

    /*
     * Prompt for input.
     */
    printf("Type a word; if you don't in 15 ");
    printf("seconds I'll use \"WORD\": ");
    fflush(stdout);

    /*
     * Now call select.  We pass NULL for
     * writefds and exceptfds, since we
     * aren't interested in them.
     */
    nfds = select(1, &readfds, NULL, NULL, &tv);

    /*
     * Now we check the results.  If nfds is zero,
     * then we timed out, and should assume the
     * default.  Otherwise, if file descriptor 0
     * is set in readfds, that means that it is
     * ready to be read, and we can read something
     * from it.
     */
    if (nfds == 0) {
        strcpy(buf, "WORD");
    }
    else {
        if (FD_ISSET(0, &readfds)) {
            n = read(0, buf, sizeof(buf));
            buf[n-1] = '\0';
        }
    }

    printf("\nThe word is: %s\n", buf);
    exit(0);
}

[root@ftosx1 My]#

Running we will simply have:

[root@ftosx1 My]# ./mytime
Type a word; if you don't in 15 seconds I'll use "WORD": Linux

The word is: Linux
[root@ftosx1 My]# ./mytime
Type a word; if you don't in 15 seconds I'll use "WORD":
The word is: WORD
[root@ftosx1 My]#
 

Limits

This section is for limits in C.

As you probably knows, the PI number 3.141516 is an irrational number. This means that will be impossible to print the exact number. We need to cut it and write an approximation, like the previous.

In particular these approximation for PI, E and other constants are present in the file: math.h.

/* Some useful constants.  */
#if defined __USE_BSD || defined __USE_XOPEN
# define M_E        2.7182818284590452354   /* e */
# define M_LOG2E    1.4426950408889634074   /* log_2 e */
# define M_LOG10E   0.43429448190325182765  /* log_10 e */
# define M_LN2      0.69314718055994530942  /* log_e 2 */
# define M_LN10     2.30258509299404568402  /* log_e 10 */
# define M_PI       3.14159265358979323846  /* pi */
# define M_PI_2     1.57079632679489661923  /* pi/2 */
# define M_PI_4     0.78539816339744830962  /* pi/4 */
# define M_1_PI     0.31830988618379067154  /* 1/pi */
# define M_2_PI     0.63661977236758134308  /* 2/pi */
# define M_2_SQRTPI 1.12837916709551257390  /* 2/sqrt(pi) */
# define M_SQRT2    1.41421356237309504880  /* sqrt(2) */
# define M_SQRT1_2  0.70710678118654752440  /* 1/sqrt(2) */
#endif

However, this section does not regards, limits in Mathematical or approximation, but just for C types.

The include file: limits.h, includes these limits.

We can note the following declarations.

/* Number of bits in a `char'.  */
#  define CHAR_BIT  8

/* Minimum and maximum values a `signed char' can hold.  */
#  define SCHAR_MIN (-128)
#  define SCHAR_MAX 127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX 255

/* Minimum and maximum values a `char' can hold.  */
#  ifdef __CHAR_UNSIGNED__
#   define CHAR_MIN 0
#   define CHAR_MAX UCHAR_MAX
#  else
#   define CHAR_MIN SCHAR_MIN
#   define CHAR_MAX SCHAR_MAX
#  endif

/* Minimum and maximum values a `signed short int' can hold.  */
#  define SHRT_MIN  (-32768)
#  define SHRT_MAX  32767

/* Maximum value an `unsigned short int' can hold.  (Minimum is 0.)  */
#  define USHRT_MAX 65535

/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN   (-INT_MAX - 1)
#  define INT_MAX   2147483647

/* Maximum value an `unsigned int' can hold.  (Minimum is 0.)  */
#  define UINT_MAX  4294967295U

/* Minimum and maximum values a `signed long int' can hold.  */
#  if __WORDSIZE == 64
#   define LONG_MAX 9223372036854775807L
#  else
#   define LONG_MAX 2147483647L
#  endif
#  define LONG_MIN  (-LONG_MAX - 1L)

/* Maximum value an `unsigned long int' can hold.  (Minimum is 0.)  */
#  if __WORDSIZE == 64
#   define ULONG_MAX    18446744073709551615UL
#  else
#   define ULONG_MAX    4294967295UL
#  endif

#  ifdef __USE_ISOC99

/* Minimum and maximum values a `signed long long int' can hold.  */
#   define LLONG_MAX    9223372036854775807LL
#   define LLONG_MIN    (-LLONG_MAX - 1LL)

For a complete check please read the limits.h file.

Some Utilities for Developers


The UNIX(r) or Linux1 Operating systems offers a complete set of utilities (also the C Compiler may be understood) like an utility, to produce software and binaries for any purpose.

Each compiled program includes a symbolic table, that may be used for debugging - See Chapter 5: The debugging of C programs.

In this section we want to list all the common utilities that "any" programer must know to get results in the development but also for a complete use of the Linux OS.

The "nm" utility

The nm lists names or symbols from object files.

For example, a classical use is the following.

[root@ftosx1 root]# nm  /usr/lib/libc.a | grep time | more

After a complicated research we will get:

...
gmtime.o:
00000000 T __gmtime_r
00000018 T gmtime
00000000 W gmtime_r
localtime.o:
00000000 T __localtime_r
00000018 T localtime
00000000 W localtime_r
mktime.o:
         U __localtime_r
00000000 T __mktime_internal
00000000 b localtime_offset
000006d8 T mktime
000006d8 W timelocal
strftime.o:
         U mktime
00000000 T strftime
time.o:
00000000 T time
gettimeofday.o:
00000000 T __gettimeofday
00000000 W __gettimeofday_internal
00000000 W gettimeofday
settimeofday.o:
00000000 T __settimeofday
00000000 W settimeofday
adjtime.o:
...
 

In BASE course we wrote an utility to browse symbolic names inside libraries. Sometimes (basically before the OpenSource wave), was fundamental to know what library was necessary to link, and a complete research is fundamental.

The "strings" utility

The strings program is another very usefull tool used to know what strings are included in libs, objects or binaries. For example if we want to know what is the version for the actual kernel running in the system, the command will be:

[root@ftosx linux]# pwd
/usr/src/linux
[root@ftosx linux]# strings vmlinux | grep gcc
Linux version 2.4.7 (root@ftosx1.futuretg.com) (gcc version 3.0.1) #13 SMP Fri Aug 24 07:51:58 EDT 2001
 

The "objdump" utility

This function get the .h file  or other info from the object file with the relative symbolic info.

  objdump -b oasys -m linux -h fu.o
 

Of course the file "fu.o" must belong to the oasys file.
 

The "objcopy" utility

This utility as explain it name,copy objects inside a file to another, without to compile, or to write programs. It uses the GNU BFD Library.
 

The "strip" utility

The strip utility more common removes the symbolic infomation inside objects or binaries.

Note the difference for example compiling the 5.3.c file.

[root@ftosx1 My]# gcc -g 5.3.c -o mytime
[root@ftosx1 My]# ls -al mytime
-rwxr-xr-x    1 root     root        18824 Jul  7 17:20 mytime
[root@ftosx1 My]# strip mytime
[root@ftosx1 My]# ls -al mytime
-rwxr-xr-x    1 root     root         3388 Jul  7 17:20 mytime
[root@ftosx1 My]#

Generally when a package is created the strip is made in automatic mode.

The "size" utility

The size instead prints the information about the symbolic information: text, and data information.

Note that the numbers does not changes stripping the binary.

[root@ftosx1 My]# gcc -g 5.3.c -o mytime
[root@ftosx1 My]# size mytime
   text    data     bss     dec     hex filename
   1333     280       8    1621     655 mytime
[root@ftosx1 My]# strip mytime
[root@ftosx1 My]# size mytime
   text    data     bss     dec     hex filename
   1333     280       8    1621     655 mytime
[root@ftosx1 My]# man size
[root@ftosx1 My]#
 

All these utilities are included in the binutils RPM package.
 

Exercises

  1. List all functions included in libc.a
  2. Discussion:  Are C++ ABI mature for gcc ? Are there some method to solve?


Test (Only 65 simple questions!)

  1. What package includes the libc.a (C Lib) ?
  2. What are the three necessary components to develop programs in C and C++ in Linux systems ?
  3. Why GNU GCC 3.1 compiler is so important ?
  4. What is the company that have the role to certify and test the GNU GCC ?
  5. What languages supports the GNU GCC 3.1 tarball ?
  6. Why is important to have a C-Preprocessor ?
  7. What program may be used to investigate what are the functions included in the libc.a ?
  8. The vi uses the libc.a ?
  9. What UNIX/Linux utilitiy may list objects inside a library ? Is this utility inolved in the Linux kernel generation ?
  10. What packages includes the C Lib "/usr/lib/libc.a" ?
  11. Suppose that we want to compile a C source that includes the file "stdio.h". What will be the command to compile it ?
  12. What will be the command to run this "just compiled" program ?
  13. What is the flag to add new include files ?
  14. What is the flag to add new libraries in the compilation time ?
  15. What is the GNU GCC option to create the binary ?
  16. What is the GCC Enviroment variable ?
  17. What is the Enviroment variable for Libraries ?
  18. We use a variable called BUFSIZ to read file, as a normal or maximal buffer size. Are there a similar variable for DIRSIZ ? What means ?
  19. What is the character to terminate a string ?
  20. Is there available a function to generate RANDOM number ? What includes file we must includes ?
  21. What is FILE ... speaking in C language ? How long is (bytes) ? What C function print it size ?
  22. What system is handled by the file "pwd.h" ? Working dir ?
  23. What you suppose is the size for a character ? What is the correct size for a character ?
  24. List three elements for the FILE type.
  25. What is the FILENAME_MAX value ?
  26. What C structure handle the file properties, owner,group and other ? What includes file define this type ?
  27. Would be possible that an include file includes another include file ? If so, Why happens this ?
  28. What is the difference between #include <stdio.h> and #include "stdio.h" ?
  29. Would we need to include the "libc.a" in the compilation, like "gcc myfile.c -l lc" or something similar ?
  30. Where are defined the stderr, stdin and stdout ?
  31. What are the minimum RPM packages to develop C programs ?
  32. The program "rpm" needs the libc to run ?
  33. Suppose that someone removes the libc.a ... how is possible to copy the lib in the original place?
  34. What include file list the fopen function ?
  35. What does the function "strtok" ?
  36. Are there some function in the C Library to get the hyperbolic sine ?
  37. Are there a function to print the BASIC function INT(X) ?
  38. Is clear to suppose that C lib includes a define for mathematical constants as PI, E, and others. What is the number of decimals on PI?
  39. What include file includes the "malloc" and "calloc" functions? What is the difference between these functions ?
  40. Are there some special functions to integer arithmetic (without to touch floats and doubles) ?
  41. Are there some function to transform numbers likes "1234" in their relative string "1234" ?
  42. How we can transform strings like "1234" in numbers ?
  43. Would be possible to duplicate an entire struct using a single C library function ?
  44. Are the signal functions connected in some way to the program "kill" ?
  45. List one function included in the file "stdlib.h".
  46. Are the strcpy, strtok function that belong to the libc?
  47. Fix in your mind the printf, that prints any quantity of arguments. How or what is possible? Using what function or declaration ?
  48. What language compiles the g77 compiler ?
  49. What command or parameter is used to create a shared library?
  50. What is the difference between libc.a and libc.so ?
  51. Is libc.a stripped? Have sense this question?
  52. The Linux kernel is stripped? Have sense this question?
  53. What is the C function to read and set the file permissions ?
  54. What is an API ?
  55. What is an ABI ?
  56. How we can solve the C error:

  57. procquery.c: In function `display_link':
      procquery.c:120: dereferencing pointer to incomplete type
      procquery.c:120: dereferencing pointer to incomplete type
  58. What does the tool "size" ?
  59. What does the tool "strip" ?
  60. What is the package that includes these tools ?
  61. What is GNU BFD ?
  62. Is possible to copy data between objects ?
  63. Would the size for symbolic info changes after the stripping process ?
  64. Is GNU GCC included in LSB (Linux Standard Specifications) 1.2 ?
  65. Are there some C function that prints the number of occurence of a string in another ?
  66. What is the version of the RedHat GCC gaffe compiler ?


Consult the answers

Check the Interactive Exam Cram Programming: Try the interactive cram ...

Internet Resources for this Chapter.



1 - Richard Stallman and its "GNU is not UNIX" at FSF (Free Software Foundation) start to offers the high fashioned UNIX powerfull style, with its GNU Utilities: gcc, gawk, sed, and others. GNU Team knows how powerfull were UNIX ... but UNIX® is a registered trademark of The Open Group, instead GNU not. In those days born the GPL to offer this power to everyone. Linus Torvalds close the task offering its Linux kernel.