Ejercicio del 22/01/08.

Anuncio
Ejercicio evaluable de Sistemas Operativos
Ingeniería Informática
Problema: Aplicar filtros y filtrar salida
Escriba un programa en C llamado ’filter’ que acepte una expresión regular como primer argumento, un
comando como segundo argumento, y a continuación un número indeterminado de parámetros para la
ejecución de dicho comando.
El programa tiene que, para cada fichero existente en el directorio actual (omitiendo cualquier directorio presente) imprimir las líneas resultantes de la ejecución del comando cuando ejecuta con dicho fichero
como entrada estandar. Las lineas impresas han de ser filtradas, de tal forma que únicamente se impriman
las que se ajustan a la expresión regular indicada.
PISTA: Se permite ejecutar comandos existentes desde C, pero no se permite ejecutar ni un shell ni
scripts.
Dos ejemplos de ejecución podrían ser:
% ls
a b
% filter ’lib$’ ls -l -s /sys
0 d-rwxrwxr-x M 19 esoriano esoriano
0 d-rwxrwxr-x M 19 esoriano esoriano
% cat a
hola
caracola
% cat b
holahola
% filter ’^$’ cat
%
0 Jan 21 13:57 /sys/lib
0 Jan 21 13:57 /sys/lib
-2-
Solución
#include <u.h>
#include <libc.h>
void
usage(void)
{
fprint(2, "usage: %s expr cmd args...\n", argv0);
exits("usage");
}
int
togrep(char* expr)
{
int
fd[2];
if(pipe(fd)<0)
sysfatal("pipe: %r");
switch(fork()){
case -1:
sysfatal("fork");
case 0:
close(fd[1]);
dup(fd[0], 0);
close(fd[0]);
execl("/bin/grep", "grep", expr, nil);
sysfatal("exec grep: %r");
default:
close(fd[0]);
return fd[1];
}
}
-3-
void
runcmd(int argc, char* argv[], char* in, int outfd)
{
char*
args[512];
// enough
char*
pname;
int
fd;
int
i;
if(argc+1 == nelem(args))
sysfatal("fixme. too many args");
for(i = 0; i < argc; i++)
args[i] = argv[i];
args[i] = nil;
switch(rfork(RFFDG|RFREND|RFPROC|RFNOWAIT)){
case -1:
sysfatal("fork: %r");
case 0:
fd = open(in, OREAD);
if(fd < 0)
sysfatal("open %s: %r", in);
dup(fd, 0);
close(fd);
dup(outfd, 1);
close(outfd);
pname = smprint("/bin/%s", args[0]);
exec(pname, args);
sysfatal("exec %s: %r", pname);
}
}
-4-
void
main(int argc, char* argv[])
{
int
gfd;
Dir*
d;
int
nd;
int
dfd;
int
i;
ARGBEGIN{
default:
usage();
}ARGEND;
if(argc < 2)
usage();
gfd = togrep(argv[0]);
argc++; argv++;
dfd = open(".", OREAD);
if(dfd < 0)
sysfatal("open .: %r");
nd = dirreadall(dfd, &d);
close(dfd);
for(i = 0; i < nd; i++)
runcmd(argc, argv, d[i].name, gfd);
if(nd > 0)
free(d);
close(gfd);
waitpid();
// can be only grep
exits(nil);
}
Descargar