#include <stdio.h> /* fgets, printf */
#include <string.h> /* strlen, strcmp, strtok */
#include <stdlib.h> /* exit, NULL, EXIT_FAILURE, EXIT_SUCCESS, free */
#include <sys/time.h> /* gettimeofday, struct timeval */
#include <sys/resource.h> /* getrusage, struct rusage, RUSAGE_SELF */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* fork, chdir, getcwd */
#include <sys/wait.h> /* waitpid */
#include <dirent.h> /* scandir, struct dirent, alphasort */
#include <sys/stat.h> /* chmod */
#include "mini-shell.h" /* MAXLINE, MAXARGS, printInformations, cd, fim
isPrimitiveCommand, executePrimitiveCommand */
int main() {
char path[PATH_MAX];
char buffer[MAXLINE];
char *command;
char * arguments[MAXARGS];
int i, primitiveCommand;
double start, finish;
struct timeval timeval;
struct rusage rusageParent, rusageChildren;
printf("\n Mini-Shell - EP1 - SO (2006)\n\n");
while (1) {
getcwd(path, PATH_MAX);
/* Lendo nova entrada */
for(i = 0; i < MAXARGS; i++) arguments[i] = NULL;
printf("%s > ", path);
fgets(buffer, MAXLINE, stdin);
/* Comecando a cronometrar o tempo de processamento */
if(gettimeofday(&timeval, NULL) != 0) perror("gettimeofday error");
start = (double)timeval.tv_sec + ((double)timeval.tv_usec * 1e-6);
/* Lendo comando */
if (strlen(buffer) > 0) buffer[strlen(buffer) - 1] = '\0';
command = strtok(buffer, " ");
if (command != NULL) {
/* Lendo argumentos */
arguments[0] = command; /* Convention (man exec) */
i = 1;
while(i < MAXARGS && (arguments[i++] = strtok(NULL, " ")) != NULL);
/* Verificando comandos primitivos do mini-shell */
if((primitiveCommand = isPrimitiveCommand(command)))
executePrimitiveCommand(command, arguments);
else
executeCommand(command, arguments);
/* Terminando de cronometrar o tempo de processamento */
if(gettimeofday(&timeval, NULL) != 0) perror("gettimeofday error");
finish = (double)timeval.tv_sec + ((double)timeval.tv_usec * 1e-6);
printf("\nInformacoes\n");
printf("- Tempo de Processamento: %.3f s\n", finish - start);
printf("\nPai:\n");
if(getrusage(RUSAGE_SELF, &rusageParent) != 0) perror("getrusage error");
else printRUsageInformation(rusageParent);
if(!primitiveCommand) {
printf("\nFilho(s):\n");
if(getrusage(RUSAGE_CHILDREN, &rusageChildren) != 0)
perror("getrusage error");
else printRUsageInformation(rusageChildren);
}
printf("\n");
}
}
exit(EXIT_SUCCESS);
}
void executeCommand(const char *command, char *const arguments[]) {
pid_t pid;
int status;
/* fork */
if ((pid = fork()) < 0) perror("fork error");
if(pid == 0) { /* Child */
execvp(command, arguments); /* Executando comando */
perror("couldn't execute");
exit(EXIT_FAILURE);
}
if((pid = wait(&status)) < 0) /* Parent */
perror("waitpid error");
}
int isPrimitiveCommand(const char *command) {
if(strcmp(command, "fim") == 0) return 1;
if(strcmp(command, "cd") == 0) return 1;
if(strcmp(command, "ls2") == 0) return 1;
if(strcmp(command, "chmod2") == 0) return 1;
return 0;
}
void executePrimitiveCommand(const char *command, char *const arguments[]) {
if(strcmp(command, "fim") == 0) fim();
else if(strcmp(command, "cd") == 0) cd(arguments[1]);
else if(strcmp(command, "ls2") == 0) ls2(arguments);
else if(strcmp(command, "chmod2") == 0) chmod_call(arguments);
}
void fim() {
printf("\n");
exit(EXIT_SUCCESS);
}
void cd(const char *path) {
if(chdir(path) != 0) perror("chdir error");
}
void ls2(char *const arguments[]) {
struct dirent **namelist;
int n;
n = scandir(".", &namelist, 0, alphasort);
if(n < 0)
perror("scandir");
else {
while(n--) {
printf("%s\n", namelist[n]->d_name);
free(namelist[n]);
}
free(namelist);
}
}
void chmod_call(char *const arguments[]) {
/*owner, group, others */
int all = 0, owner = 0, group = 0, others = 0;
if(arguments[1] == NULL || arguments[2] == NULL) {
perror("chmod: poucos argumentos");
return;
}
all = atoi(arguments[1]);
owner = all / 100;
group = (all % 100) / 10;
others = all % 10;
if(myChmod(arguments[2], owner, group, others) != 0)
perror("myChmod error");
}
/*
7 XWR
1 X
2 W
4 R
S_IRWXU Read, write, execute/search by owner.
S_IRUSR Read permission, owner.
S_IWUSR Write permission, owner.
S_IXUSR Execute/search permission, owner.
S_IRWXG Read, write, execute/search by group.
S_IRGRP Read permission, group.
S_IWGRP Write permission, group.
S_IXGRP Execute/search permission, group.
S_IRWXO Read, write, execute/search by others.
S_IROTH Read permission, others.
S_IWOTH Write permission, others.
S_IXOTH Execute/search, others.
*/
int myChmod(const char* path, int owner, int group, int others) {
mode_t o = 0, g = 0, t = 0;
if(owner / 4) {
o = S_IRUSR;
owner -= 4;
}
if(owner / 2) {
o = o|S_IWUSR;
owner -= 2;
}
if(owner / 1) {
o = o|S_IXUSR;
}
if(group / 4) {
g = S_IRGRP;
group -= 4;
}
if(group / 2) {
g = g|S_IWGRP;
group -= 2;
}
if(group / 1) {
g = g|S_IXGRP;
}
if(others / 4) {
t = S_IROTH;
others -= 4;
}
if(others / 2) {
t = t|S_IWOTH;
others -= 2;
}
if(others / 1) {
t = t|S_IXOTH;
}
return chmod(path, o|g|t);
}
void printRUsageInformation(struct rusage rusage) {
printf("- Tempo de Usuario: %ld ms\n",
(rusage.ru_utime.tv_sec * 1000) +
(rusage.ru_utime.tv_usec / 1000));
printf("- Tempo de Sistema: %ld ms\n",
(rusage.ru_stime.tv_sec * 1000) +
(rusage.ru_stime.tv_usec / 1000));
printf("- Numero de Page Faults: %ld\n", rusage.ru_minflt);
printf("- Numero de Page Reclaims: %ld\n", rusage.ru_majflt);
printf("- Numero de Sinais Recebidos: %ld\n", rusage.ru_nsignals);
printf("- Mudancas de Contexto Voluntarias: %ld\n", rusage.ru_nvcsw);
printf("- Mudancas de Contexto Involuntarias: %ld\n", rusage.ru_nivcsw);
}
sábado, 4 de setembro de 2010
Uma implementação em C de um Mini-Shell
Sistemas Operacionais é bem legal, né? Esse é um Mini-Shell com comandos de mudança e listagem de diretórios (cd e ls) e também de mudança de permissões de arquivos (chmod).
Assinar:
Postar comentários (Atom)
Boa tarde meu caro,
ResponderExcluirPoderia me ajudar?? Quando mandei rodar, nao foi encontrado a biblioteca que voce denominou de mini-shell.h.
Voce teria como disponibilizar??
Grato.