Uma forma comum de passar argumentos a programas é através da linha de comandos. Uma linha de comandos simplificada consiste num conjunto de palavras separadas por espaços que no seu conjunto representam um determinado comando e os seus argumentos. Quando um utilizador invoca um comando através da linha de comandos, a shell apanha a linha de comando como uma string, determina nessa string qual a palavra correspondente ao comando do utilizador e constrói um vector de strings com os argumentos a passar ao programa que irá executar o comando. De seguida executa o programa passando-lhe os argumentos determinados.
Neste exercício pretende-se que implemente um programa que mostre uma
prompt ao utilizador (por exemplo, my_prompt$
),
leia as strings correspondentes aos comandos que o utilizador for
invocando, e para cada string lida chame uma função
parse()
para estruturar os argumentos correspondentes ao
comando invocado e uma função print_parse()
para imprimir
o conteúdo da estrutura retornada por
parse()
. O programa deve terminar quando o utilizador
invocar o comando exit
na linha de comandos. Para tal,
considere o extracto de código que se segue e complete-o de acordo com
as indicações abaixo:
#include <stdio.h> #include <stdlib.h> #include <readline/readline.h> #include <readline/history.h> #define MAXARGS 100 typedef struct command { char *cmd; // string apenas com o comando int argc; // número de argumentos char *argv[MAXARGS+1]; // vector de argumentos do comando } COMMAND; COMMAND parse(char *linha); void print_parse(COMMAND com); int main() { char *linha; COMMAND com; while (1) { if ((linha = readline("my_prompt$ ")) == NULL) exit(0); if (strlen(linha) != 0) { add_history(linha); com = parse(linha); print_parse(com); } free(linha); } } COMMAND parse(char *linha) { // ... } void print_parse(COMMAND com) { // ... } |
Para obter a string da linha de comando, o código acima usa as bibliotecas
readline e
history
que permitem fazer edição e historial da linha de comandos de forma
simples. A utilização destas bibliotecas requer que o programa seja
compilado com a opção -lreadline
.
A função parse()
deverá retornar uma estrutura do tipo
COMMAND
em que COMMAND
é a estrutura
de dados sugerida para estruturar os argumentos do comando invocado. O
campo cmd
possui o comando propriamente dito, o campo
argc
contém o número de argumentos, enquanto que o
campo argv
possui o vector de argumentos do comando. O
primeiro argumento é o próprio comando (argv[0] = cmd
),
seguem-se os argumentos correspondentes aos argumentos do comando
(argv[1]
, ..., argv[argc-1]
) e termina com o
argumento NULL (argv[argc] = NULL
). Para percorrer a
string do comando utilize a função
strtok()
.
A função print_parse()
deverá imprimir o conteúdo da
estrutura COMMAND
retornada por parse()
e no
caso do comando invocado ser exit
deverá terminar.
Quando a sua linha de comandos estiver a funcionar corretamente,
repita o exercício mas altere a declaração da
variável com
na função main()
por COMMAND *com
e faça as adaptações necessárias ao
restante código.