Como criar um shell simples em C?

Como criar um shell simples em C?
O shell é como um programa que recebe entradas de comando do teclado do usuário e as envia para uma máquina a ser executada pelo kernel. Ele também verifica se as entradas de comando do usuário estão corretas. Pode ser uma interface da linha de comando, como a que criaremos ou uma interface gráfica do usuário, como software normal, como o Microsoft Office ou o Adobe Suite.

Este tutorial o guiará através dos estágios de criação de um shell simples independente em C. Depois de concluir este tutorial, você deve entender melhor os vários processos e funções envolvidos, bem como uma maneira clara de codificar por si mesmo.

Qual é a vida básica da concha?

Durante sua vida útil, uma concha realiza três tarefas principais.

  • Inicializar: Nesta fase, um shell típico lerá e executará seu conjunto de arquivos de configuração. Estes alteram o comportamento da concha.
  • Interpretar: O shell então lê comandos de "stdin" e os executa.
  • Rescindir: Após a execução de seus comandos, o shell executa qualquer um dos comandos de desligamento, libera qualquer memória e termina.

Esses estágios são gerais e podem ser aplicáveis ​​a uma ampla gama de programas, mas nós os usaremos como base para o nosso shell. Nosso shell será tão básico que não haverá arquivos de configuração nem comando de desligamento. Então, simplesmente executaremos a função de loop e depois sairemos. No entanto, é essencial lembrar que a vida do programa é mais do que apenas loop.

Como criar um shell simples em C?

Criaremos um shell básico em C que demonstrará os fundamentos de como ele funciona. Como seu objetivo é demonstração em vez de integridade ou até adequação para uso casual, ele possui várias limitações, incluindo

  • Todos os comandos devem ser digitados em uma linha.
  • O espaço em branco deve ser utilizado para separar argumentos.
  • Não haverá citando ou escape de espaço em branco.
  • Não há tubulação ou redirecionamento.
  • Os únicos embutidos são 'cd', 'ajuda' e 'saída'.

Agora dê uma olhada em um programa C que está construindo uma concha simples.

#incluir
#incluir
#incluir
#incluir
#incluir
#incluir
int komal_cd (char ** args);
int komal_help (char ** args);
int komal_exit (char ** args);
char *construído_in_string [] =

"cd",
"ajuda",
"saída"
;
int (*construído_in_function []) (char **) =

& komal_cd,
& komal_help,
& komal_exit
;
int komal_builtins ()

retorno sizeof (construído_in_string) / sizeof (char *);

int komal_cd (char ** args)

if (args [1] == null)

fprintf (stderr, "Komal: argumento esperado para" cd "\ n");

outro

if (chdir (args [1]) != 0)

Perror ("Komal");


retornar 1;

int komal_help (char ** args)

int i;
printf ("Este é o shell C simples por Komal Batool \ n");
printf ("Tipo de nomes e argumentos do programa e hit Enter.\ n ");
printf ("Os seguintes são construídos em: \ n");
para (i = 0; i < komal_builtins(); i++)

printf (" %s \ n", construído_in_string [i]);

printf ("Use o comando man para obter informações sobre outros programas.\ n ");
retornar 1;

int komal_exit (char ** args)

retornar 0;

int komal_launch (char ** args)

pid_t pid;
status int;
pid = fork ();
if (pid == 0)

if (Execvp (args [0], args) == -1)

Perror ("Komal");

saída (exit_failure);
else if (pid < 0)

Perror ("Komal");

outro

fazer

waitpid (pid, & status, wuntracted);
enquanto (!Wifexited (status) && !Wifsignaled (status));

retornar 1;

int komal_execute (char ** args)

int i;
if (args [0] == null)

retornar 1;

para (i = 0; i < komal_builtins(); i++)
if (strcmp (args [0], construído_in_string [i]) == 0)
return (*construído_in_function [i]) (args);


return komal_launch (args);

char *komal_read_line (void)

#ifdef komal_use_std_getline
char *linha = nulo;
ssize_t bufsize = 0;
if (getLine (& line, & bufsize, stdin) == -1)

if (feof (stdin))

saída (exit_success);

outro

perror ("Komal: getLine \ n");
saída (exit_failure);


linha de retorno;
#outro
#define komal_rl_bufsize 1024
int bufsize = komal_rl_bufsize;
int position = 0;
char * buffer = malloc (sizeof (char) * bufsize);
int c;
se (!amortecedor)
fprintf (stderr, "komal: erro de alocação \ n");
saída (exit_failure);

enquanto (1)

c = getchar ();
if (c == eof)

saída (exit_success);

caso contrário, se (c == '\ n')

buffer [Position] = '\ 0';
retornar buffer;
outro
buffer [posição] = c;

posição ++;
if (posição> = bufsize)

bufsize += komal_rl_bufsize;
buffer = realloc (buffer, bufsize);
se (!amortecedor)

fprintf (stderr, "komal: erro de alocação \ n");
saída (exit_failure);



#fim se

#define komal_tok_bufsize 64
#define komal_tok_delim "\ t \ r \ n \ a"
char ** komal_split_line (linha *linha)

int bufsize = komal_tok_bufsize, posição = 0;
char ** tokens = malloc (bufsize *sizeof (char *));
char *token, ** tokens_backup;
se (!tokens)

fprintf (stderr, "komal: erro de alocação \ n");
saída (exit_failure);

token = strtok (linha, komal_tok_delim);
enquanto (token != Nulo)

tokens [posição] = token;
posição ++;
if (posição> = bufsize)

bufsize += komal_tok_bufsize;
tokens_backup = tokens;
tokens = realloc (tokens, bufsize * sizeof (char *));
se (!tokens)

grátis (tokens_backup);
fprintf (stderr, "komal: erro de alocação \ n");
saída (exit_failure);


token = strtok (null, komal_tok_delim);

tokens [posição] = nulo;
retornar tokens;

void komal_loop (void)

CHAR *LINE;
char ** args;
status int;
fazer

printf (">");
linha = komal_read_line ();
args = komal_split_line (linha);
status = komal_execute (args);
Linha gratuita);
grátis (args);
while (status);

int main (int argc, char ** argv)

komal_loop ();
return exit_success;

Descrição do código

O código acima é uma implementação simples de um shell da linha de comando escrito em c. A concha é nomeada “Komal”, E pode executar comandos internos, como "CD", "Ajuda" e "Exit", além de comandos externos. A principal função do programa é o “Komal_loop” Função, que se rende continuamente, lendo a entrada do usuário por meio do “Komal_read_line” função, dividindo a entrada em argumentos individuais usando o “Komal_split_line” função, e executando o comando usando o “Komal_execute” função.

O “Komal_execute” A função verifica se o comando é um comando interno e, se assim for, executa a função interna correspondente. Se o comando não for um comando integrado, ele executa um comando externo bingando um processo infantil e chamando o “Execvp” Chamada do sistema para substituir o espaço de memória do processo infantil pelo programa desejado.

O "Komal_cd", "Komal_help", e “Komal_exit” funções são as três funções internas que podem ser executadas pelo usuário. “Komal_cd” Altera o diretório de trabalho atual, “Komal_help” Fornece informações sobre o shell e seus comandos internos e “Komal_exit” sai da concha.

Saída

Conclusão

Construir um shell simples em C envolve entender como analisar e executar comandos, lidar com a entrada e saída do usuário e gerenciar processos usando chamadas do sistema como garfo e EXECVP. O processo de criação de um shell requer uma compreensão profunda da linguagem de programação C e do sistema operacional UNIX. No entanto, com a ajuda das etapas e exemplo fornecidos no guia acima, pode -se criar um shell básico que possa lidar com os comandos de entrada do usuário e executar comandos.