Trabalho I: Mini-Shell para UNIX

Objectivo

O objectivo principal deste trabalho é fornecer aos alunos um primeiro contacto com programação avançada em UNIX tendo como base a linguagem C. Em particular, pretende-se que os alunos sejam capazes de lidar com argumentos passados através da linha de comando e com chamadas de sistema para manipulação de processos, tais como: fork, pipe, dup2, exec, wait, exit, entre outras.

Trabalho

O trabalho é composto por um conjunto de pequenas etapas que no conjunto levarão à implementação de uma mini-shell para UNIX. A implementação de cada etapa deve ser o mais robusta possível, i.e., se uma chamada a uma função do sistema falhar, o programa em execução deve apresentar uma mensagem de erro apropriada e eventualmente terminar com um código de exit correcto. Para tal, procure tirar partido das funções de sistema perror ou strerror para gerar mensagens de erro apropriadas. Como exemplo, considere o código que se segue (em que syscall deve ser substituído pela função a usar):
 if (syscall(args) == ERRO) {
      perror("syscall"); 
      exit(1); 
   }

Em nenhuma etapa deve fazer uso das funções de sistema system ou popen. Como alternativa, deve recorrer sempre às funções de sistema fork, dup2 e da família exec.

Etapa 1: Linha de comandos

Use o exercício da primeira aula prática para implementar o tratamento da linha de comandos da mini-shell.

Etapa 2: Comandos simples

Estenda a mini-shell de forma a executar comandos do utilizador. Comece por considerar comandos sem argumentos e depois admita argumentos para os comandos. Assuma que o número máximo de argumentos para um comando é 100 (#define MAXARGS 100). Exemplos:

Etapa 3: Redirecionamento de input

Estenda a mini-shell para lidar com redirecionamento simples de input. A shell deve procurar pelo caracter < e, caso encontre, deve tratar a palavra que se lhe segue como o nome de um ficheiro. O input para o comando (parte antes de <) deve ser lido do ficheiro em vez do standard input. Se o ficheiro não puder ser lido, deve ser gerado um erro e o comando não deve ser executado. Exemplos:

Etapa 4: Redirecionamento de output

Estenda a mini-shell para lidar com redirecionamento simples de output. A shell deve procurar pelo caracter > e, caso encontre, deve tratar a palavra que se lhe segue como o nome de um ficheiro. O output que o comando (parte antes de >) gera deve ser enviado para o ficheiro em vez de para o standard output. Se o ficheiro já existir, deve ser re-escrito. Se o ficheiro não puder ser criado, deve ser gerado um erro e o comando não deve ser executado. Exemplos:

Etapa 5: Encadeamento de comandos

Estenda a mini-shell de forma a suportar o encadeamento de comandos (uso de pipes). A shell deve procurar pelo caracter | e, caso encontre, deve tratar as palavras que se lhe seguem como sendo um segundo comando. O output que o comando inicial (parte antes de |) gera deve ser enviado para uma pipe em vez de para o standard output. Por sua vez, o segundo comando (parte depois de |) deve tomar o seu input a partir da pipe utilizada pelo primeiro comando para enviar o seu output. Numa segunda fase estenda a mini-shell de forma a que possa encadear mais do que uma pipe na linha de comandos. Exemplos:

Etapa 6: Concorrência

Estenda a sua mini-shell para lidar com concorrência de processos. A shell deve procurar pelo caracter & e, caso encontre, deve executar o comando (parte antes do &) concorrentemente com a própria shell, ou seja, a shell não deverá esperar que o comando em causa termine para apresentar a prompt e desse modo aceitar novos comandos. Se o caracter & não for o último caracter da linha de comandos, deve ser gerado um erro e o comando não deve ser executado. Exemplos:

Etapa 7: Junção final

Caso tenha resolvido separadamente as funcionalidades das etapas anteriores, junte agora tudo num só programa de forma a que a mini-shell aceite a combinação dos vários comandos. Se já tiver todo o desenvolvimento integrado, não tem nada a fazer nesta etapa. Exemplos:

Prazos

O trabalho deve ser entregue via web até às 12 horas do dia 11 de Abril de 2008, sendo a sua demonstração feita na aula prática imediatamente a seguir.

O que entregar? Um ficheiro .tar que inclua:

O código deve compilar e executar nas máquinas da sala das aulas práticas. Uma boa estruturação e legibilidade do código será valorizada.