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.