Para adicionar à shell a possibilidade de redireccionar o standard input e o standard output de e para ficheiros temos de usar a system call dup2:
$ man dup2
Esta system call faz com que o descritor passado no segundo parâmetro aponte para o mesmo ficheiro que o primeiro. Se o segundo descritor já estava aberto, este é fechado primeiro. Depois de chamar esta função tanto faz usar o primeiro como o segundo descritor.
Para que é que isto nos serve? O programa que vamos lançar com exec() vai ler e escrever sempre nos mesmos descritores: 0 (stdin) e 1 (stdout). Para fazer com que ele escreva no ficheiro que queremos basta fazer com que estes descritores apontem não para a consola (por omissão) mas para esse ficheiro. Tendo um descritor aberto para o ficheiro chamado fd basta efectuar uma destas duas chamadas antes de lançar o exec():
// Redireccionar standard input
dup2(fd, STDIN_FILENO);
// Redireccionar standard output
dup2(fd, STDOUT_FILENO);
int fd = open(filename, O_RDONLY);
int fd = creat(filename, 0644);
int redir_in(const char* file)
{
int fd = open(file, O_RDONLY);
if(dup2(fd, STDIN_FILENO) == -1)
return -1;
if(close(fd) == -1)
return -1;
}
int redir_out(const char* file)
{
int fd = creat(file, 0644);
if(dup2(fd, STDOUT_FILENO) == -1)
return -1;
if(close(fd) == -1)
return -1;
}
Agora na função run temos de fazer os redireccionamentos:
int run(char** args, int background, const char* command, char* in, char* out)
{
pid_t pid = fork();
if(pid == 0)
{
// Efectuar redireccionamento quando pedido
if(in)
redir_in(in);
if(out)
redir_out(out);
execvp(args[0], args);
perror(args[0]);
exit(1);
}
else
{
// ...
}
}
Já só falta alterar a função getArgs para ter em conta os redireccionamentos. Infelizmente a wordexp não aceita strings com |, &, ;, <, >, (, ), { ou }. Por isso eu usei ] e [ para os nossos redireccionamentos, para não perder muito tempo com parsing, já que a parte importante do exercício era usar dup2 correctamente.
getArgs agora vai receber como parâmetro apontadores para strings para “devolver” os nomes dos ficheiros para redireccionar. Se não houver redireccionamento essas strings ficar com NULL.
char** getArgs(const char* s, char** in, char** out);
E na função main:
char *in, *out;
in = out = NULL;
while(/*...*/)
{
char** args = getArgs(command, &in, &out);
// ...
run(args, background, command, in, out);
// ...
}
Se tiverem dificuldades a alterar getArgs, façam download do código e vejam como fiz.
[1] Era por isso que a camisola que o prof mostrou na primeira aula tinha ”Tirei 024 a Sistemas Operativos” escrito. Porque 24(8) = 20(10) e em C qualquer constante númerica que comece por 0 é octal:
#include <stdio.h>
void main()
{
if(024 == 24)
printf("They're equal!\n");
else
printf("WTF? 024 != 24?\n");
if(024 == 20)
printf("024 == 20! It's octal!\n");
printf("%d in octal is %o!\n", 20, 20);
}
0 commentários:
Enviar um comentário