Examen de Fundamentos de Sistemas Operativos Tiempo total: 2.5 horas. Problema: Llamadas al sistema (3.5 puntos) Implemente un programa copy que copie un fichero en otro. Si el fichero destino existe, se debe truncar. Si no existe, se debe crear. Si únicamente se proporciona un argumento, el programa debe copiar su entrada estándar. Por ejemplo: term% copy a b1 term% copy b2 < a term% cmp b1 b2 term% Entrega: Copie un fichero llamado copy-login.c, donde login es tu nombre de usuario, en el directorio /usr/elf/examen. ATENCIÓN: Sólo se puede efectuar la entrega una vez. Ponga un comentario con su nombre y apellidos en el fichero. -2- Solución _____ _copy.c #include <u.h> #include <libc.h> enum{ Bufsize = 8 * 1024, }; void usage(char *name) { fprint(2, "usage: %s [file] file\n", name); exits("usage"); } void main(int argc, char *argv[]) { int fdin = -1; int fdout = -1; long nr; char buf[Bufsize]; if(argc == 2){ fdin = 0; fdout = create(argv[1], OWRITE, 0660); }else if(argc == 3){ fdin = open(argv[1], OREAD); if(fdin < 0) sysfatal("open file: %r"); fdout = create(argv[2], OWRITE, 0660); }else usage(argv[0]); if(fdout < 0) sysfatal("create: %r"); while(((nr = read(fdin, buf, Bufsize)) > 0)) if(write(fdout, buf, nr) != nr) sysfatal("write: %r"); if(nr < 0) sysfatal("read: %r"); if(fdin != 0) close(fdin); close(fdout); exits(nil); } -3- Problema: Shell Script (3 puntos) Escriba un script de RC llamado nproc.rc que reciba el nombre de un programa y escriba por su salida estándar el número de procesos que están ejecutando dicho programa. Si se le pasa el modificador -p debe escribir el PID de los procesos en lugar del número de procesos. Por ejemplo: term% nproc.rc acme 4 term% nproc.rc -p acme 312 443 456 677 term% Entrega: Copie un fichero llamado nproc-login.rc, donde login es tu nombre de usuario, en el directorio /usr/elf/examen. ATENCIÓN: Sólo se puede efectuar la entrega una vez. Ponga un comentario con su nombre y apellidos en el fichero. -4- Solución ________ nproc.rc #!/bin/rc fn usage { echo ’usage [-p] name’ >[1=2] exit usage } if (! ~ $#* 1 2) { usage } if(~ $#* 2){ if (! ~ $1 ’-p’) { usage } echo ‘{ps | grep ’[ ]’^$2^’$’ | awk ’{print $2}’} } if not{ echo ‘{ps | grep ’[ ]’^$1^’$’ | wc -l} } -5- Problema: Llamadas al sistema (3.5 puntos) Implemente un programa paragz que descomprima en paralelo todos los ficheros gzip que se le pasan como argumentos. En caso de que haya un error en cualquiera de los ficheros, el programa debe avisar y terminar de forma apropiada después de que todos los ficheros hayan sido procesados. Por ejemplo: term% paragz uno.gz dos.gz tres.gz some errors: error processing dos.gz term% Entrega: Copie un fichero llamado paragz-login.c, donde login es tu nombre de usuario, en el directorio /usr/elf/examen. ATENCIÓN: Sólo se puede efectuar la entrega una vez. Ponga un comentario con su nombre y apellidos en el fichero. -6- Solución ________ paragz.c #include <u.h> #include <libc.h> void usage(char *name) { fprint(2, "usage: %s file [file ...] \n", name); exits("usage"); } int gunzip(char *path) { if(access(path, AREAD) != 0){ fprint(2, "error processing %s\n", path); return 1; } switch(fork()){ case -1: sysfatal("fork failed %r"); case 0: execl("/bin/gunzip", "gunzip", path, nil); sysfatal("exec failed, error processing %s", path); } return 0; } void main(int argc, char *argv[]) { int errs = 0; int i; Waitmsg *msg; if(argc < 2) usage(argv[0]); for(i = 1; i < argc; i++) errs += gunzip(argv[i]); while((msg = wait()) != nil){ if(msg->msg[0] != 0) errs++; free(msg); } if(errs){ fprint(2, "some errors\n"); exits("errors"); } exits(nil); }