Understanding Echo Utility In Shell Scripting

Discussion in 'C' started by lionaneesh, Mar 5, 2012.

  1. lionaneesh

    lionaneesh Active Member

    Joined:
    Mar 21, 2010
    Messages:
    848
    Likes Received:
    224
    Trophy Points:
    43
    Occupation:
    Student
    Location:
    India
    In this tutorial, we'll be looking at the code structure of the 'echo' utility and will try to understand how it works, for those who are unfamilliar with the 'echo' utility, its one of the most basic and most useful utilities in a shell it prints out its arguments on the standard output, if you have some shell scripting experience, most probably you must have used it and actually most of output related shell scripts use this utility.

    The Code



    Source of Echo

    Code:
    /* $NetBSD: echo.c,v 1.18 2008/09/18 05:42:08 dholland Exp $    */
    
    /*
     * Copyright (c) 1989, 1993
     *      The Regents of the University of California.  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. Neither the name of the University nor the names of its contributors
     *    may be used to endorse or promote products derived from this software
     *    without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE.
     */
    
    #include <sys/cdefs.h>
    #ifndef lint
    __COPYRIGHT(
    "@(#) Copyright (c) 1989, 1993\
     The Regents of the University of California.  All rights reserved.");
    #endif /* not lint */
    
    #ifndef lint
    #if 0
    static char sccsid[] = "@(#)echo.c      8.1 (Berkeley) 5/31/93";
    #else
    __RCSID("$NetBSD: echo.c,v 1.18 2008/09/18 05:42:08 dholland Exp $");
    #endif
    #endif /* not lint */
    
    #include <locale.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int, char *[]);
    
    /* ARGSUSED */
    int
    main(int argc, char *argv[])
    {
            int nflag;
    
            setprogname(argv[0]);
            (void)setlocale(LC_ALL, "");
    
            /* This utility may NOT do getopt(3) option parsing. */
            if (*++argv && !strcmp(*argv, "-n")) {
                    ++argv;
                    nflag = 1;
            }
            else
                    nflag = 0;
    
            while (*argv) {
                    (void)printf("%s", *argv);
                    if (*++argv)
                            (void)putchar(' ');
            }
            if (nflag == 0)
                    (void)putchar('\n');
            fflush(stdout);
            if (ferror(stdout))
                    exit(1);
            exit(0);
            /* NOTREACHED */
    }
    
    More that 1/3rd the code is the liscense, copyright info etc. We can just ignore that part for now and focus on the real code.

    Code:
    int
    main(int argc, char *argv[])
    
    The above code defines the main function (often the entry point of a C program), argc and argv are argument count and argument verctor respectively.

    Code:
            int nflag;
    
    “nflag” is used to indicate whether the program is given a “-n” as an argument or not.

    The next 2 lines are again configuration based and we'll not be digging into this for the scope of this tutorial.
    Code:
                   if (*++argv && !strcmp(*argv, "-n")) {
                    ++argv;
                    nflag = 1;
            }
            else
                    nflag = 0;
    
    Note we are pre-incremneting the argv before using as argv[0] is the name of the program itself i.e “./echo” in our case, basically we are checking if we have the first argument and if yes, then we check if its “-n” i.e nflag, if both the conditions evaluate to true we simply increment the argument vector and set the nflag, else we set it to 0.

    Now comes the main part, this is where the real meat of the program lies.

    Code:
     while (*argv) {
                    (void)printf("%s", *argv);
                    if (*++argv)
                            (void)putchar(' ');
            }
    
    We loop through the arguent vector and keep printing it, with SPACES in between.

    Code:
            if (nflag == 0)
                    (void)putchar('\n');
    
    Then we simply print a newline if the "nflag" was not set, and the end we flush the output buffer and exit.


    Conclusion



    The motive of this tutorial was to provide a foundation to code reading and how to go about reading code written by other programmers. 'ECHO' was the utility with the most basic code-base i could find, which can serve as a good starting point for beginners.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice