1. O documento descreve a implementação de uma shell simples chamada MyShell em C como um trabalho prático de sistemas operacionais.
2. A MyShell implementa comandos básicos como ls, pwd, cd e também funções como execução em segundo plano e pipes.
3. A implementação inclui funções para tratar cada comando, utilizando primitivas do sistema operacional como fork, execv e wait para criar e gerenciar processos.
O que é arte. Definição de arte. História da arte.
MyShell
1. Universidade Federal de Ouro Preto
Instituto de Ciências Exatas e Biológicas
Departamento de Computação
BCC264 - Sistemas Operacionais
Terceiro Trabalho Prático
Johnnatan Messias
Pollyanna Gonçalves
Wellington Dores
Professor - Fabrício Benevenuto
Ouro Preto
1 de junho de 2011
4. 1 Introdução
Este trabalho tem por objetivo fazer com que os alunos se familiarizem com o
ambiente Unix, desenvolvam habilidades de programação defensiva em C, aumentem
sua exposição às funcionalidades de interpretadores de comandos e coloquem em
prática conceitos sobre gerência de processos (p.ex., disparo e terminação).
1.1 Considerações iniciais
• Sistema Operacional utilizado: Ubuntu 11.04
• Ambiente de desenvolvimento: NetBeans IDE C/C++
• Ambiente de desenvolvimento da documentação: TeXnicCenter 1 Editor de
LTEX.
A
1.2 O Problema
Implementar uma shell mínima, a M yShell, para colocar em prática os princípios
de manipulação de processos. Esse tipo de conhecimento é essencial no desenvolvi-
mento de sistemas complexos com diversos processos, como no caso de servidores.
1.2.1 Linguagem da MyShell
A linguagem compreendida pela M yShell é bem simples. Cada sequência de
caracteres diferentes de espaço é considerada um termo. Termos podem ser oper-
ações internas da shell, nomes de programas que devem ser executados, argumentos
a serem passados para os comandos ou programas e operadores especiais. Oper-
ações internas da shell são as sequências de caracteres cd, pwd, wait e exit. Essas
operações devem sempre terminar com um sinal de m de linha (return) e devem
ser entradas logo em seguida ao prompt (isto é, devem sempre ser entrados como
linhas separadas de quaisquer outros comandos). Operadores são os símbolos (back-
ground) e | (pipe), quando ocorrem isoladamente (como um único caractere entre
espaços). Programas a serem executados são identicados pelo nome do seu ar-
quivo executável e podem ser seguidos por um número máximo de dez argumentos
(parâmetros que serão passados ao programa através do vetor argv[]. Cada comando
de disparo deve terminar com um dos operadores, ou com o m de linha.
• Fim de linha: indica que o processo deve ser disparado e a myshell deve esperar
pelo seu m antes de exibir outro prompt.
• Background: o processo deve ser disparado e a M yShell deve continuar sua
execução. Isso pode signicar a continuação da interpretação da linha de co-
mandos, se há outros comandos na linha, ou o retorno imediato ao prompt.
Cada vez que um processo é disparado em background, M yShell deve ex-
ibir uma mensagem a esse respeito, com o identicador (pid) do processo em
questão.
• Pipe: o conteúdo após o operador deve ser interpretado outro comando a ser
executado, sendo que a saída padrão do primeiro processo deve ser conectada
1
5. à entrada padrão do processo seguinte. Para simplicar a implementação,
M yShell não permite o encadeamento de pipes, isto é, não é permitido colo-
car outro pipe na saída do segundo programa. Pode-se, entretanto, colocar
ambos os programas em background terminando a sequência com o operador
apropriado (nesse caso, uma mensagem sobre a operação em background deve
ser exibida para cada processo).
Os comandos internos têm as seguintes interpretações:
• CD: muda o diretório corrente da shell. Isso terá impacto sobre os arquivos
visíveis sem um caminho completo (path).
• PWD: exibe o diretório corrente visto pelo processo.
• WAIT: faz com que a shell espere pelo término de todos os processos que
possam estare m execução antes de exibir um novo prompt. Cada processo
que seja encontrado durante um wait deve ser informado através de uma men-
sagem na linha de comando. Caso não haja processos pelos quais esperar, uma
mensagem a respeito deve ser exibida e M yShell deve continuar sua execução.
• EXIT: termina a operação da shell se não há processos em background. Caso
contrário, exibe uma mensagem informando o fato e realiza a operação wait
antes de terminar.
2 A implementação da MyShell
Mais adiante apresentamos a implementação das funções que trata um comando
qualquer que vai ser digitado pelo usuário na M yShell, algumas das funções primi-
tivas que serão utilizadas em outras funções estão explicadas abaixo:
• Primitiva f ork(): única chamada de sistema que possibilita a criação de um
processo em U N IX .
• Primitiva execv(): função em que o primeiro argumento corresponde ao cam-
inho completo para o executável ou script a ser executado e o segundo é o
nome do programa a ser executado.
• Primitiva wait(): suspende a execução do processo pai até a morte de seu
processo lho (se o lho já estiver morto, a função retorna -1, imediatamente).
• Primitiva exit(): ADICIONAR!!!!
Algumas bibliotecas da linguagem C que foram utilizadas para a execução do
programa:
• errno.h
• signal.h
• sys/types.h
• sys/wait.h
• unistd.h
2
6. 2.1 Tratamento da Entrada de dados
A função split, representada abaixo, trata a entrada de dados do usuário na
M yShell utilizando funções auxiliares da biblioteca string.h denidas na linguagem.
1
char ∗∗ split ( char ∗∗ linha , char ∗∗ vString , char ∗∗ comando , int ∗ tam ) {
char ∗
int
tok = NULL ;
char ∗ sizeof char
i ;
5 tok = ( ) malloc ( ( ) ∗200) ;
s t r c p y ( tok , ∗ linha ) ;
tok = s t r t o k ( tok , n ) ;
∗ comando = s t r t o k ( tok , ) ;
10
// P o s i ç ã o 0 reservada para o execv
vString [ 1 ] = s t r t o k (NULL, ) ;
if ( ! vString [ 0 ] )
15 vString [ 0 ] = ;
for ( i = 2; vString [ i −1]; i ++){
vString [ i ] = s t r t o k (NULL, ) ;
}
20
vString [ i − 1] = NULL ;
∗ tam = ( i − 1) ;
return
f r e e ( tok ) ;
25 vString ;
}
Programa 1: Função split
2.2 Função para comando Ls
O comando ls, em U N IX , mostra o conteúdo de um diretório passado como
argumento. A função abaixo implementada recebe como parâmetro (em forma de
string ) os argumentos que foram passados pelo usuário da M yShell: 2
void meu_ls ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / l s ;
5 pid_cd = fork () ;
if ( pid_cd == 0)
else
execv ( / b i n / l s , vArgumentos ) ;
10
int
{
status1 ;
w a i t ( s t a t u s 1 ) ; // e s p e r a a morte de um filho
}
}
Programa 2: Função ls
3
7. 2.3 Função para comando Pwd
O comando pwd, em U N IX , apresenta o diretório corrente do usuário da M yShell.
Uma implementação para essa função é apresentada em: 3
void meu_pwd ( char ∗∗ vArgumentos )
{
vArgumentos [ 0 ] = / b i n / pwd ;
5
int pid = fork () ;
if ( pid == 0)
{
10 p r i n t f ( n ) ;
e x e c v ( / b i n / pwd , vArgumentos ) ;
p r i n t f ( n ) ;
else
}
15
int
{
status1 ;
w a i t ( s t a t u s 1 ) ;
}
20 }
Programa 3: Função pwd
2.4 Função para comando Cd
O comando cd, em U N IX , abre o diretório passado como argumento pelo usuário
da M yShell. Uma implementação para essa função é apresentada em: 4
void meu_cd ( char ∗∗ vArgumentos )
{
int pid_cd = 0;
5
if ( pid_cd == 0)
char
{
cwd [ 2 0 4 8 ] ;
cwd [ 0 ] = ' 0 ' ;
10
if ( g e t c w d ( cwd , 2048) != NULL)
if
{
( c h d i r ( vArgumentos [ 1 ] ) != 0)
{
15 printf ( It wasn ' t possible set current directory to / n
) ;
}
}
else
}
20
int
{
status1 ;
w a i t ( s t a t u s 1 ) ;
}
4
8. 25 }
Programa 4: Função cd
Para a implementação dessa função utilizamos as funções getcwd() (retorna o
nome completo do diretório corrente) e chdir (muda o diretório corrente para aquele
passado como parâmetro).
2.5 Função para comando Cat
O comando cat, em U N IX , combina um ou mais arquivos e os apresenta na
saída padrão, ou seja, mostra o conteúdo de um arquivo passado como argumento
pelo usuário da M yShell. Uma implementação para essa função é apresentada em:
5
void meu_cat ( char ∗∗ vArgumentos )
{
vArgumentos [ 0 ] = / b i n / c a t ;
5
int pid_cat = fork () ;
if ( pid_cat == 0)
else
execv ( / b i n / c a t , vArgumentos ) ;
10
int
{
status1 ;
w a i t ( s t a t u s 1 ) ;
}
15 }
Programa 5: Função cat
2.6 Função para comando Grep
O comando cat, em U N IX , procura por linhas em arquivos que correspondam
a um padrão especicado pelo usuário da M yShell e as apresenta. Uma implemen-
tação para essa função é apresentada em: 6
void meu_grep ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / grep ;
5
if
pid = fork () ;
( pid == 0)
{
p r i n t f ( n ) ;
execv ( / b i n / grep , vArgumentos ) ;
10 p r i n t f ( n ) ;
else
}
int
{
15 status1 ;
w a i t ( s t a t u s 1 ) ;
}
5
9. }
Programa 6: Função grep
2.7 Função para comando Ping
O comando ping , em U N IX , envia pacotes ICM P para um determinado host
e mede o tempo de resposta. Uma implementação para essa função é apresentada
em: 7
void meu_ping ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / ping ;
5
if
pid = fork () ;
( pid == 0)
{
p r i n t f ( n ) ;
execv ( / b i n / ping , vArgumentos ) ;
10 p r i n t f ( n ) ;
else
}
int
{
15 status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 7: Função ping
2.8 Função para comando Kill
O comando kill, em U N IX , envia sinais a determinados processos em execução.
Por padrão é enviado o sinal SIGT ERM que requisita a nalização de um processo.
Em geral é utilizado na forma 1 , onde pid é o identicador do processo que pode
ser obtido através do comando ps 14. Uma implementação para essa função é
apresentada em: 8
void meu_kill ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / k i l l ;
5
if
pid = fork () ;
( pid == 0)
{
p r i n t f ( n ) ;
execv ( / b i n / k i l l , vArgumentos ) ;
10 p r i n t f ( n ) ;
else
}
int
{
15 status1 ;
1 kill pid
6
10. w a i t ( s t a t u s 1 ) ;
}
}
Programa 8: Função kill
2.9 Função para comando Date
O comando date, em U N IX , simplesmente exibe a data e a hora atual do sistema
no prompt da M yShell. Uma implementação para essa função é apresentada em:
9
void meu_date ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / d a t e ;
5
if
pid = fork () ;
( pid == 0)
{
p r i n t f ( n ) ;
execv ( / b i n / d a t e , vArgumentos ) ;
10 p r i n t f ( n ) ;
else
}
int
{
15 status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 9: Função date
2.10 Função para comando Mkdir
O comando mkdir, em U N IX , cria um diretório no diretório atual da M yShell.
Uma implementação para essa função é apresentada em: 10
void meu_mkdir ( char ∗∗ vArgumentos )
{
int
vArgumentos [ 0 ] = / b i n / mkdir ;
5
if
pid = fork () ;
( pid == 0)
{
p r i n t f ( n ) ;
execv ( / b i n / mkdir , vArgumentos ) ;
10 p r i n t f ( n ) ;
else
}
int
{
15 status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
7
11. Programa 10: Função mkdir
2.11 Função para comandos Mv, Rm e RmDir
Os comandos mv , rm e rmdir, em U N IX , move (ou renomeia) um diretório ou
cheiro, remove um determinado cheiro e um remove um diretório, respectivamente.
Uma implementação para essa função é apresentada em: 11
void meu_mv( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n /mv ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
e x e c v ( / b i n /mv , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
15
void meu_rm ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n /rm ;
if
pid = fork () ;
20 ( pid == 0) {
p r i n t f ( n ) ;
e x e c v ( / b i n /rm , vArgumentos ) ;
p r i n t f ( n ) ;
25 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
30
void meu_rmdir ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / rmdir ;
35
if
pid = fork () ;
( pid == 0) {
p r i n t f ( n ) ;
execv ( / b i n / rmdir , vArgumentos ) ;
p r i n t f ( n ) ;
40
else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
45 }
Programa 11: Funções Rm, Mv e RmDir
8
12. 2.12 Função para comando Cp
O comando cp, em U N IX , permite que o usuário faça cópia de um cheiro para
outro, onde o primeiro cheiro (passado como argumento) é lido e copiado para o
segundo (no caso da inexistência desse, o mesmo é criado). Uma implementação
para essa função é apresentada em: 12
void meu_cp ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / cp ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
e x e c v ( / b i n / cp , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 12: Função cp
2.13 Função para comando Chmod
O comando chmod, em U N IX , permite que o usuário altere as permissões de
um cheiro ou diretório no formato drwxrwxrwx, respectivamente: diretório (d),
permissão do dono (read/write/execute), do grupo (read/write/execute) e de outros
(read/write/execute). Uma implementação para essa função é apresentada em: 13
void meu_chmod ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / chmod ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
e x e c v ( / b i n / chmod , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 13: Função chmod
2.14 Função para comando Ps
O comando ps, em U N IX , lista a lista de processos em execução, geralmente
utilizado quando se necessita para saber o pid de um processo terminá-lo com o
comando kill. Uma implementação para essa função é apresentada em: 14
void meu_ps ( char ∗∗ vArgumentos ) {
9
13. int
vArgumentos [ 0 ] = / b i n / ps ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
execv ( / b i n / ps , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 14: Função ps
2.15 Função para comando Sh e Bash
Os comandos sh e bash, em U N IX , são interpretadores de comandos feitos para
intermediar o usuário e seu sistema. Através deles, o usuário manda um comando,
e o interpretador o executa no sistema. Eles são a shelldo sistema. Uma imple-
mentação para essa função é apresentada em: 15
void meu_sh ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / sh ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
execv ( / b i n / sh , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
15
void meu_bash ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / bash ;
if
pid = fork () ;
20 ( pid == 0) {
p r i n t f ( n ) ;
execv ( / b i n / bash , vArgumentos ) ;
p r i n t f ( n ) ;
25 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 15: Funções Sh e Bash
10
14. 2.16 Função para comando Sleep
O comando sleep, em U N IX , é usado para dar um tempo antes de começar um
novo processo pela M yShell. Uma implementação para essa função é apresentada
em: 16
void meu_sleep ( char ∗∗ vArgumentos ) {
int
vArgumentos [ 0 ] = / b i n / s l e e p ;
if
pid = fork () ;
5 ( pid == 0) {
p r i n t f ( n ) ;
execv ( / b i n / s l e e p , vArgumentos ) ;
p r i n t f ( n ) ;
10 else
int
} {
status1 ;
w a i t ( s t a t u s 1 ) ;
}
}
Programa 16: Função sleep
2.17 Função para comando Pipe e Background
O comando (pipe), em U N IX , que faz o encadeamento de processosou
seja, ele permite que a saída de um comando seja diretamente utilizado em outro
comando. Já o comando (background) permite que um processo seja executado
em segundo plano, ou seja, a M yShell não cará impedida de inicializar outros
processos durante a execução do anterior. Uma implementação para essas funções
é apresentada em: 17
int isPipeOrBk ( char ∗ linha ){
int i , tam = strlen ( linha ) − 1;
5 for
if
( i =0; i tam ; i ++)
return
(( linha [ i ] == '| ') || ( linha [ i ] == ' ' ) ) {
1;
return
}
0;
10 }
Programa 17: Função Pipe ( )eBackground()
Ao receber o comando do usuário utilizamos a função isP ipeOrBk para vericar
em O(n) se o comando contém ou não os caracteres ou . Caso tenha, a função
retornará 1 e 0 caso contrário.
2.18 Função para comando Exit
O comando exit, em U N IX , termina a execução da M yShell se não há processos
em background, caso contrário a ação deverá ser tratada. Uma implementação para
essa função é apresentada em: 18
11
15. void meu_cat ( char ∗∗ vArgumentos )
{
vArgumentos [ 0 ] = / b i n / c a t ;
5
int pid_cat = fork () ;
if ( pid_cat == 0)
else
execv ( / b i n / c a t , vArgumentos ) ;
10
int
{
status1 ;
w a i t ( s t a t u s 1 ) ;
}
15 }
Programa 18: Função Exit
2.19 Função Principal
Abaixo apresentamos a função principal para o funcionamento da M yShell. No
corpo da função principal main é feita a entrada dos dados pelo usuário (comandos
e argumentos para tais) e o tratamento de cada caso, chamando as respectivas
funções que tratam o comando necessitado e ao nal desaloca a memória utilizada
na execução do programa. A implementação da função é apresentada abaixo: 19
/ ∗ Mini −i n t e r p r e t a d o r ∗/
#include s t d i o . h
5 #include s t d l i b . h
#include s t r i n g . h
#include u n i s t d . h
10
#include f u n c o e s . h
int int char ∗∗ a r g v )
int
main ( argc , {
linesize = 512; // Tamanho da linha de comando
15
char ∗
char ∗∗
linha = NULL ; // Linha de Comando
int
vArgumentos = NULL ; // Vetor de argumentos
char ∗
tam = 0; // Quantidade de Argumentos
int
comando = NULL ; // Comando a ser executado
20 i , linhaMatriz = 40 , colunaMatriz = 100; // dimensoes do vetor
int
de argumentos
char ∗ sizeof char ∗
pos ;
char ∗ ∗ sizeof char ∗
linha = ( ) malloc ( ( ) 512) ;
∗ linhaMatriz ) ;
char ∗ sizeof char
vArgumentos = ( ) malloc ( ( )
vArgumentos [ 0 ] = ( ) malloc ( ( ) ∗( linhaMatriz ∗
for
colunaMatriz ) ) ;
25 ( i = 1; i linhaMatriz ; i ++)
vArgumentos [ i ] = ( v A r g u m e n t o s [ 0 ] [ i ∗ colunaMatriz ] ) ;
12
16. p r i n t f ( nMYSHELL : ) n ) ;
30
p r i n t f ( DEBUG: PID %d , PPID %d n n , getpid () , getppid () ) ; // pid −
Process ID ppid − Parent Process ID
while (1) {
35 char cwd [ 2 0 4 8 ] ; // P a s t a atual
cwd [ 0 ] = ' 0 ' ;
if ( g e t c w d ( cwd , 2048) == NULL) { //
40 p e r r o r ( Nao foi possivel obter o diretorio atual .
Padronizando para / n ) ;
s t r c p y ( cwd , / ) ;
if ( c h d i r ( cwd ) != 0) {
45 p e r r o r ( Nÿo foi possivel acessar o diretorio a t u a l . n
) ;
}
}
50 newline :
p r i n t f ( M y S h e l l :~% s $ , cwd ) ;
f g e t s ( linha , linesize , stdin ) ;
55 if n ) == 0 )
goto
( strcmp ( l i n h a ,
newline ; // s e m p r e que nÿo hý comandos volta para
newline
if ( isPipeOrBk ( l i n h a ) ) {
continue
system ( l i n h a ) ;
60 ;
}
vArgumentos = s p l i t ( l i n h a , vArgumentos , comando , tam ) ; //
Guarda os comandos no vetor de args .
65 //A partir desse ponto procura pelo comando digitado e chama a
funcao correspondente
if ( strcmp ( h e l p , comando ) == 0) {
meu_help ( ) ;
70 } else if ( strcmp ( c r e d i t o s , comando ) == 0) {
creditos () ;
} else if ( strcmp ( l s , comando ) == 0) {
meu_ls ( v A r g u m e n t o s ) ;
75
} else if ( strcmp ( e x i t , comando ) == 0) {
meu_exit ( 0 ) ;
} else if ( s t r c m p ( pwd , comando ) == 0) {
80 meu_pwd ( v A r g u m e n t o s ) ;
13
17. } else if ( strcmp ( cd , comando ) == 0) {
meu_cd ( v A r g u m e n t o s ) ;
85 } else if ( strcmp ( c a t , comando ) == 0) {
meu_cat ( v A r g u m e n t o s ) ;
} else if ( strcmp ( w a i t , comando ) == 0) {
meu_wait ( ) ;
90
} else if ( s t r c m p ( , comando ) == 0) {
meu_background ( ) ;
} else if ( strcmp ( p i n g , comando ) == 0) {
95 meu_ping ( v A r g u m e n t o s ) ;
} else if ( strcmp ( k i l l , comando ) == 0) {
m e u _ k i l l ( vArgumentos ) ;
100 } else if ( strcmp ( d a t e , comando ) == 0) {
meu_date ( v A r g u m e n t o s ) ;
} else if ( strcmp ( gr ep , comando ) == 0) {
meu_grep ( v A r g u m e n t o s ) ;
105
} else if ( strcmp ( mkdir , comando ) == 0) {
meu_mkdir ( v A r g u m e n t o s ) ;
} else if ( s t r c m p ( mv , comando ) == 0) {
110 meu_mv( v A r g u m e n t o s ) ;
} else if ( s t r c m p ( rm , comando ) == 0) {
meu_rm ( v A r g u m e n t o s ) ;
115 } else if ( strcmp ( rmdir , comando ) == 0) {
meu_rmdir ( v A r g u m e n t o s ) ;
} else if ( strcmp ( cp , comando ) == 0) {
meu_cp ( v A r g u m e n t o s ) ;
120
} else if ( s t r c m p ( chmod , comando ) == 0) {
meu_chmod ( v A r g u m e n t o s ) ;
} else if ( strcmp ( echo , comando ) == 0) {
125 meu_echo ( v A r g u m e n t o s ) ;
} else if ( strcmp ( hostname , comando ) == 0) {
meu_hostname ( v A r g u m e n t o s ) ;
130 } else if ( strcmp ( ps , comando ) == 0) {
meu_ps ( v A r g u m e n t o s ) ;
} else if ( strcmp ( sh , comando ) == 0) {
meu_sh ( v A r g u m e n t o s ) ;
135
} else if ( strcmp ( bash , comando ) == 0) {
meu_bash ( v A r g u m e n t o s ) ;
14
18. } else if ( s t r c m p ( nano , comando ) == 0) {
140 meu_nano ( v A r g u m e n t o s ) ;
} else if ( strcmp ( s l e e p , comando ) == 0) {
meu_sleep ( vArgumentos ) ;
145 } else {
p r i n t f ( Comando '% s ' nÿo encontrado ! n , comando ) ;
}
linha [ 0 ] = ' 0 ' ;
150 }
f r e e ( vArgumentos [ 0 ] ) ;
f r e e ( vArgumentos ) ;
}
Programa 19: Função Main
Aqui é feita a vericação com a função isP ipeOrBk 17 de modo a escolher qual
será o uxo de execução do programa de duas maneiras:
• Caso a função isP ipeOrBk retorne 1, ou seja, tendo como instrução a execução
de um comando em Background ou utilização do Pipe chamamos o comando
System do Linux para fazer uma chamada ao Sistema de modo a executar
esses comandos.
• Caso não haja o programa será executado normalmente de modo que nós é
que contralamos a criação dos processos lhos e da execução dos comandos
contidos no
bin.
Note que também estamos utilizando uma matriz para guardar os dados que
serão passados pelo usuário da M yShell. Para essa matriz de char(ou seja, vetor de
strings) foi feita uma alocação com a quantidade de linhas da matriz de adjacên-
cias e mais uma alocação para a posição matriz[0] com tamanho Linha ∗ Coluna,
fazendo, em seguida, um redirecionamento dos endereços da matriz. Para melhor
entendimento, vide Figura 1
Figura 1: Representação da Alocação de Matriz
15