Writing a Basic Shell

2019-03-08 01:04发布

For my class I have to create a basic shell similar to bash that will allow the user to call commands like ls, sleep, etc. I am looking for resources on how to do this: tutorials, help text, sample code or even just some general information on how to get started. Does anyone have an links or info to help me out?

标签: c bash shell
7条回答
看我几分像从前
2楼-- · 2019-03-08 01:25

I wrote a very basic shell for the HelenOS project. It has the following features:

  • Line editing / history
  • Buit in commands / loadable commands
  • Search path to find external commands
  • EXTREMELY basic scripting
  • Dumbed down implementations of most of the GNU core utilities (done from scratch) as built in functions.

Most of it is implemented on a very simple re-usable framework built around function pointers. At the minimum, you'll need a built in 'exit' or 'quit' so someone can actually get out of the shell, plus 'cd' and 'pwd'. An 'export' / 'declare' built in would also make sense.

You can look at the code (BSD) licensed here. Or download the repo, it's in uspace/app/bdsh. I can probably dig up the last working Linux version, prior to when I ported it if you need it. The biggest difference is the HelenOS version uses a home grown line editor, task_spawn() instead of execve() / posix_spawn(), etc. The rest is portable. It was originally designed just to make testing of features easy and interactive. I didn't implement job control, as it wasn't needed. That could be achieved trivially, however.

If you want to study a 'real' shell, I highly recommend looking at dash, you'll find it much simpler to grasp than diving straight into the code of bash.

Anecdotally, 'bdsh' stands for 'brain dead shell'.

查看更多
时光不老,我们不散
3楼-- · 2019-03-08 01:26

It really depends on how simple your shell has to be. If you don't need job control (i.e. backgrounding) or pipes then it is very simple. Here is an example:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LENGTH 1024

int main(int argc, char *argv[]) {
  char line[MAX_LENGTH];

  while (1) {
    printf("$ ");
    if (!fgets(line, MAX_LENGTH, stdin)) break;
    system(line);
  }

  return 0;
}

You can exit from the above example with CTRL-D. To add built-in commands like exit or cd you would have to tokenize the line using strtok() and look at the first token. Here is a more complicated example with those commands added:

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

#ifdef _WIN32
#include <windows.h>
#define chdir _chdir

#else
#include <unistd.h>
#endif

#define MAX_LENGTH 1024
#define DELIMS " \t\r\n"

int main(int argc, char *argv[]) {
  char *cmd;
  char line[MAX_LENGTH];

  while (1) {
    printf("$ ");
    if (!fgets(line, MAX_LENGTH, stdin)) break;

    // Parse and execute command
    if ((cmd = strtok(line, DELIMS))) {
      // Clear errors
      errno = 0;

      if (strcmp(cmd, "cd") == 0) {
        char *arg = strtok(0, DELIMS);

        if (!arg) fprintf(stderr, "cd missing argument.\n");
        else chdir(arg);

      } else if (strcmp(cmd, "exit") == 0) {
        break;

      } else system(line);

      if (errno) perror("Command failed");
    }
  }

  return 0;
}

You could extend this by adding more build-in commands or by supporting things like cd with out arguments to change to your home directory. You could also improve the command prompt by adding information such as the current directory.

As a side note, an easy way to add a command history and line editing features is to use the GNU readline library.

查看更多
Lonely孤独者°
4楼-- · 2019-03-08 01:31

You could look at BusyBox for some very small shell implementations.

查看更多
beautiful°
5楼-- · 2019-03-08 01:35

Lowball answer:

If the program is very simple, then simple system calls can be implemented script-like with the command "system("putdesiredcommandhere");"

When you install "printf" in a program, you are doing a simple system call, with the help of stdio.h.

Small code sample follows.

#include <stdio.h>
#include <stdlib.h>
main ()
{
    system ("clear");
    system ("echo this is an example of a basic system call");
    printf ("just as you've always done.\n");

    return 0;
}

Using that method, you could transcribe bash or csh scripts into a c program. It would require using a system call for each line in the script.

查看更多
Deceive 欺骗
6楼-- · 2019-03-08 01:42

If you are starting , try http://stephen-brennan.com/2015/01/16/write-a-shell-in-c/ and further for detailed knowledge http://www.gnu.org/software/libc/manual/html_node/Data-Structures.html#Data-Structures .

Also , while learning how to program a shell using C/C++ make a habit to refer man pages of commands.

查看更多
Lonely孤独者°
7楼-- · 2019-03-08 01:43

Bash provides very few commands on its own: cd, pushd, popd, the variable handling routines (set and $x), and all of the control flow items like loops and conditionals. Almost all other commands are found in the $PATH.

Unless the assignment states otherwise, ignore variables and control flow. Just provide a REPL that looks in $PATH and executes whatever the user enters (presumably through posix_spawn()) and pass along the command-line arguments.

查看更多
登录 后发表回答