Examen de Fundamentos de Sistemas Operativos, Ing. Teleco. Septiembre 2009 Problema: Llamadas al sistema Escriba en C para Plan 9 un programa llamado inv que acepte como argumentos un nombre para una variable de entorno y un comando con un número indeterminado de argumentos. Tras ejecutar el programa, la variable de entorno especificada debe contener la salida del comando pasado como argumento. A continuación se muestra un ejemplo: term% inv a echo uno dos tres term% echo $a uno dos tres term% -2- Solución _____ inv.c #include <u.h> #include <libc.h> void main(int argc, char *argv[]) { char** args; char* cmd; char* fname; int fd; int i; argv0 = argv[0]; if(argc < 3){ fprint(2, "usage: %s var cmd...", argv0); exits("usage"); } fname = smprint("/env/%s", argv[1]); if(argv[2][0] != ’/’ && (argv[2][0] != ’.’ || argv[2][1] != ’/’)) cmd = smprint("/bin/%s", argv[2]); else cmd = argv[2]; argv += 2; argc -= 2; args = malloc(sizeof(char*) * (argc + 1)); if(fname == nil || cmd == nil || args == nil) sysfatal("no memory"); for(i = 0; i < argc; i++) args[i] = argv[i]; args[i] = nil; fd = create(fname, OWRITE, 0664); if(fd < 0) sysfatal("%s: %r", fname); dup(fd, 1); close(fd); /* * args, fname, cmd memory released during exec. */ exec(cmd, args); remove(fname); sysfatal("exec %s: failed", cmd); } No necesitamos crear ningún proceso. Podemos hacer que el comando escriba directamente su salida en la variable. Podríamos haber utilizado otro proceso, un pipe y putenv. -3- Problema: Script de Shell Crear un script llamado includes.rc que imprima todos los ficheros de cabecera incluidos en los ficheros fuente en C que se encuentren en el directorio actual. Puede considerarse que los ficheros fuente son aquellos con extensión ‘‘.c’’ o ‘‘.cpp’’. Puede haber ficheros que se incluyan más de una vez, pero sólo deben imprimirse una única vez. No importa el orden de aparición. Puede suponerse que las directivas #include no contienen espacios en blanco dentro de los ángulos o comillas y tampoco tienen espacio en blanco tras el carácter ‘‘#’’. -4- Solución __________ includes.rc #!/bin/rc rfork e hdrs=‘{grep -h ’^#include[ ]’ *.c *.cpp |\ sed ’s/[">][ ]*$//’ |\ sed ’s|.*<|/sys/include/|’ |\ sed ’s/.*"//’ |\ sort -u } for(h in $hdrs) cat $h exit ’’ El comando cuya salida se asigna a la variable hdrs es el responsable de hacer todo el trabajo, luego resta volcar el contenido de los ficheros a la salida estándar. La llamada a grep se ocupa de imprimir sólo las líneas conteniendo declaraciones include, pero sin imprimir (por el flag -h) el nombre de fichero ni número de línea. A partir de ahí, podemos eliminar el último carácter tras el nombre del archivo y luego eliminar todo el texto hasta el carácter que indica el comienzo del nombre de archivo. Al eliminar este último trozo de la linea (el prefijo hasta el nombre de archivo) aprovechamos para reemplazar el texto por /sys/include si la directiva empleada se refiere a ficheros estándar del sistema, dejando el nombre de fichero inalterado en otro caso. Al final, sort ordena la lista de ficheros y el flag -u se ocupa de eliminar duplicados.