LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   programming a linux shell using the c programming language (https://www.linuxquestions.org/questions/linux-newbie-8/programming-a-linux-shell-using-the-c-programming-language-4175434345/)

alexantosh 10-27-2012 07:54 AM

programming a linux shell using the c programming language
 
hi every one. well straight to the point. am trying to build a simple linux shell(command line) using the c programming line and cygwin on windows machine. the shell will implement a few easy linux commands like ,cd, ls, pwd, using child processes and fork() function i guess- but i couldnt even make the cursor appear yet on my shell so far!

any help or form of assistance provided is greatly appreciated in advance. reply ASAP
thanks.

tronayne 10-27-2012 01:01 PM

How about and example (taken from Chapter 6, Stephen G. Kochan, Patrick H. Wood, Topics in C Programming, rev. ed., 1991):
Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>

void        main        (void)
{
        char        line [BUFSIZ];
        int        process;

        for ( ; ; ) {
                (void) fprintf (stderr, "cmd: ");
                if (gets (line) == (char *) NULL)
                        exit (EXIT_FAILURE);
                /*        create new process        */
                if ((process = fork ()) > 0)
                        (void) wait ((int *) NULL);
                else if (process == 0) {        /* child        */
                        /*        execute program                        */
                        (void) execlp (line, line, NULL);
                        /*        some problem if exec returns        */
                        (void) fprintf (stderr, "can't execute %s\n", line);
                        exit (errno);
                } else if (process == -1) {        /* can't create        */
                        (void) fprintf (stderr, "can't fork\n");
                        exit (errno);
                }
        }
}

That'll get you started.

And a second example, also for Chapter 6 of the same work:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>

/*
 *        simple command interpreter
 *        supports < and > redirection and command line arguments
*/

int        breakup        (char *, char **);

void        main        (void)
{
        char        line [BUFSIZ], *args [15];
        int        process, nargs;

        process = 0;
        for ( ; ; ) {                /* loop forever                        */
                (void) fprintf (stderr, "cmd: ");
                if (gets (line) == (char *) NULL) {
                        exit (EXIT_SUCCESS);
                }
                if ((process = fork ()) > 0)        /* parent        */
                        (void) wait ((int *) NULL);
                else if (process == 0) {        /* child        */
                        /*        parse command line                */
                        nargs = breakup (line, args);
                        /*        make sure there's something        */
                        if (nargs == 0)
                                exit (EXIT_SUCCESS);
                        /*        execute program                        */
                        (void) execvp (args [0], args);
                        /*        some problem if execvp returns        */
                        (void) fprintf (stderr, "cannot execute %s\n", line);
                        exit (errno);
                } else if (process == -1) {        /* can't create        */
                        (void) fprintf (stderr, "can't fork\n");
                        exit (errno);
                }
        }
}

/*
 *        break up command line and return in "args"
 *        recognize < file and > file constructs and redirect
 *        standard input and output as appropriate
*/

int        breakup        (char *line, char *args [])
{
        char        *strptr = line, *file;
        int        nargs = 0;

        while ((args [nargs] = strtok (strptr, " \t")) != (char *) NULL) {
                strptr = (char *) NULL;
                /*        output redirection        */
                if (args [nargs] [0] == '>') {
                        if (args [nargs][1] != '\0')
                                file = &args [nargs] [1];
                        else {
                                file = strtok (strptr, " \t");
                                if (file == (char *) NULL) {
                                        (void) fprintf (stderr, "no file after >\n");
                                        return (0);
                                }
                        }
                        (void) close (1);
                        if (open (file, O_WRONLY | O_TRUNC | O_CREAT, 0666) == -1) {
                                (void) fprintf (stderr, "can't open %s for output\n", file);
                                return (0);
                        }
                        --nargs;
                /*        input redirection        */
                } else if (args [nargs] [0] == '<') {
                        if (args [nargs] [1] != '\0')
                                file = &args [nargs] [1];
                        else {
                                file = strtok (strptr, " \t");
                                if (file == (char *) NULL) {
                                        (void) fprintf (stderr, "no file after <\n");
                                        return (0);
                                }
                        }
                        (void) close (0);
                        if (open (file, O_RDONLY) == -1) {
                                (void) fprintf (stderr, "can't open %s for input\n", file);
                                return (0);
                        }
                        --nargs;
                }
                ++nargs;
        }
        args [nargs] = (char *) NULL;
        return (nargs);
}

This one you can fiddle around with and implement pipes and other features (it already supports redirection (< and >).

You might want to look around for a newer edition of Topics; it's an excellent learning-by-example work.

Hope this helps some.

alexantosh 10-27-2012 05:20 PM

heey, i dont know who you are but i definitely know that you have gotten me going. Thanks a great deal!! now i guess i have no excuses!! :) let me get on with the fiddling and i will let you know as i proceed!

tronayne 10-28-2012 07:59 AM

Yer welcome -- you might want to pick up a copy of that book: full of working, useful examples and well written. Amazon is a good place to look.

Best of luck with it.

theNbomr 10-28-2012 09:37 AM

I think it is helpful to think of a shell as a way to expose kernel/system functionality to the end-user. Most of the things a typical shell does map directly, sometimes a bit indirectly, to core system functions, such as launching process, opening/reading/writing files & devices, setting process state like current working directory & the shell's environment, etc. On top of all of that is the built-in programming/scripting capability, which isn't completely necessary, but is a convenience.
I suggest that you use readline() from libreadline as the basis for your commandline processing.
--- rod.

alexantosh 10-28-2012 01:36 PM

i guess i have to buy it from amazon. tried looking out for pdfs. no luck so far. so, to amazon i go!

alexantosh 10-29-2012 06:07 PM

thanks
 
thanks alot guys, am almost done with my little shell. but now i have to implement the "batch mode". ideeaaass? :)

chrism01 10-29-2012 11:48 PM

You'll need to ask your teacher what they mean by 'batch mode' as *nix doesn't actually have that concept....
Possibly they mean cron http://www.adminschoice.com/crontab-quick-reference ?

alexantosh 10-30-2012 04:49 AM

well, i hear the shell wont then display a prompt when in this mode. it will just read the commands from a pre-written batch file and then simply display the commands and their out put. to activate or enter this mode i shoud type [batchfile] on the command prompt where "batchFile" is the name of the batch file prewritten.

chrism01 10-30-2012 05:14 AM

Ok, that sounds more like reading and acting upon a shell file aka script file, which would make sense.
All a shell/script file really is, is a collection of cmds that you could run direct from the cli manually.

See these links
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/

theNbomr 10-30-2012 08:24 AM

And to implement that, I would guess that you are expected to exercise some file-descriptor gymnastics, possibly involving pipe(), popen(), dup(), dup2(), and other functions that are probably referenced in the 'SEE ALSO' sections of the respective man pages.

--- rod.

alexantosh 10-30-2012 10:25 AM

thanks for the links and tips. the book links look good but they appear to need some time, so i will first take a look at the dup() function usage. 'coz i didnt expect this feature to take a lot of time. but i am planning on making a fully functioning shell so even if my project is done am sure to keep going.
by the way, for the record: you guys are alot of help really, this blog isn't just for show. you show lost sheep the way to light.
I LIKE THAT :)


All times are GMT -5. The time now is 02:30 AM.