unix shell

18 01 2009

O interpretador de comandos dos sistemas operacionais Unix e Unix-like é a interface tradicional para operar o computador. Por meio de comandos, o usuário direciona o sistema para tarefas específicas.

O interpretador, conhecido como shell, normalmente suporta uma linguagem de script para que os comandos possam ser executados de maneira sequencial, permitindo automatizar tarefas rotineiras.

Mas, internamente, o que faz o shell? Bem, as etapas básicas são as seguintes:

  1. imprime o prompt de comando: $ para usuário ou # para root
  2. lê a linha digitada pelo usuário
  3. remove CRLF (\r\n) e depois separa a linha em strings, onde houver espaço
  4. fork(): duplica o conteúdo do próprio processo (parent) no sistema, criando um processo filho (child)
    • no child: execvp() executa o comando digtado – tipo ls -l
    • no parent: wait(NULL) aguarda o processo filho terminar

Embora os shells mais avançados como bash e csh possuam uma enorme quantidade de funções, tais como as da biblioteca readline, um shell apenas com as etapas mencionadas acima funciona perfeitamente.

Aqui está o exemplo:

/* 20090118 - AF */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

static char *stripcrlf(char *line)
{
    char *p;
    for(p = line; *p; p++)
        if(*p == '\r' || *p == '\n') { *p = '\'; break; }
    return line;
}

static void split(char *line, char **args)
{
    while(*line) {
        while(*line && *line == ' ') *line++ = '\';
        *args++ = line;
        while(*line && *line != ' ') line++;
    }
}

int main()
{
    char *p, line[4096], *args[sizeof line/2];

    for(;;) {
        fprintf(stdout, getuid() ? "$ " : "# ");
        fflush(stdout);

        memset(line, 0, sizeof line);
        if(!fgets(line, sizeof line, stdin)) {
            fprintf(stdout, "\n");
            clearerr(stdin);
            continue;
        }

        p = stripcrlf(line);
        if(*p) split(p, args);
        else continue;

        if(!fork()) {
            if(execvp(args[0], args) == -1) perror("exec");
        } else wait(NULL);
    }
    return 0;
}

NOTA: a imagem no topo foi criada por Paul Bourke em 1989, encontrada neste site.


Ações

Informações

Deixe um comentário