Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 [Cuestión 1.]Resuelva con una orden UNIX las siguientes tareas: Apartado a.- Copie todas las rutas de los directorios donde el intérprete de comandos busca los programas ejecutables al final del fichero rutas.txt situado en el directorio temporal del sistema. echo $PATH >> /tmp/rutas.txt Apartado b.- Modifique los permisos del fichero pdatos.txt del directorio precursos de su directorio de usuario de tal forma que el propietario tenga todos los perm isos sobre él, el grupo sólo lectura y ejecución, y el resto de usuarios, sólo posean permiso de lectura. Chmod 754 $HOME/precursos/pdatos.txt Apartado c.- Mostrar un listado con información sobre los directorios del sistema (a cualquier nivel) cuyo nombre empieza por “bin” y sólo tienen permiso de lectura para el propietario. El grupo y otros no disponen de permiso de lectura. Los permisos de escritura y ejecución no nos importan. ls –lR / | grep “bin[^ ]*$” |grep “^dr..-..-..“ Apartado d.- Copiar el contenido existente, a cualquier nivel, que se encuentra en el directorio padre del directorio actual al subdirectorio copia que se encuentra en el directorio que indica la variable de entorno BACKUP. Cp –R .. $BACKUP/copia Puntuación: 2 ptos. Tiempo estimado: 10 min. 1 2 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 [Cuestión 2.]Debe implementarse en C un programa denominado ficheros_regulares_ejecutables, que admita como parámetro la ruta absoluta de un directorio y muestre por pantalla la ruta y el tamaño en bytes de los ficheros regulares contenidos, a cualquier nivel, en dicho directorio que tengan al menos permiso de ejecución para el propietario. Si se ejecuta el programa ficheros_regulares_ejecutables sin indicar ningún argumento adicional, se mostrará el siguiente mensaje: Uso: ficheros_regulares_ejecutables <directorio> En la figura 1 aparece un fragmento de un ejemplo de ejecución de este programa: murillo:/export/home/examen> ./ficheros_regulares_ejecutables /sbin Directorio = /sbin Ruta del archivo ejecutable = /sbin/su Tamanno = 23400 bytes Ruta del archivo ejecutable = /sbin/autopush Tamanno = 219860 bytes Ruta del archivo ejecutable = /sbin/dhcpagent Tamanno = 522380 bytes Ruta del archivo ejecutable = /sbin/dhcpinfo Tamanno = 496588 bytes Ruta del archivo ejecutable = /sbin/fdisk Tamanno = 274800 bytes Ruta del archivo ejecutable = /sbin/in.mpathd Tamanno = 526872 bytes Ruta del archivo ejecutable = /sbin/init Tamanno = 554536 bytes Ruta del archivo ejecutable = /sbin/jsh Tamanno = 308480 bytes Ruta del archivo ejecutable = /sbin/mount Tamanno = 262396 bytes Ruta del archivo ejecutable = /sbin/netstrategy Tamanno = 454280 bytes Ruta del archivo ejecutable = /sbin/rc0 Tamanno = 2792 bytes Ruta del archivo ejecutable = /sbin/sh Tamanno = 308480 bytes Ruta del archivo ejecutable = /sbin/bpgetfile Tamanno = 8892 bytes Ruta del archivo ejecutable = /sbin/setbootdev Tamanno = 266824 bytes Ruta del archivo ejecutable = /sbin/apboot Tamanno = 65348 bytes Ruta del archivo ejecutable = /sbin/apcheck Tamanno = 212112 bytes Figura 1: Fragmento de un ejemplo de ejecución del programa ficheros_regulares_ejecutables. NOTAS: − Debe comprobarse que el segundo argumento que se indica en la línea de comandos es un directorio. − Para determinar si el propietario tiene permiso de ejecución puede emplear la constante S_IXUSR. − Los errores que se produzcan deberán mostrarse por la salida estándar de error. − No se puede utilizar la llamada a system. Puntuación: 2 ptos. Tiempo estimado: 25 min. /***********************************************************/ /*********************** ejercicio2.c *********************/ /***********************************************************/ #include #include #include #include #include <stdio.h> <sys/stat.h> <sys/file.h> <dirent.h> <fcntl.h> #define LONGITUD_MAX 255 void obtener_entradas_directorio (char *); 3 int main(int argc, char* argv[]) { struct stat atributos; if (argc != 2) { printf("Uso: %s <directorio>\n", argv[0]); exit (-1); } // Obtenemos información del segundo argumento (archivo o directorio) if (stat(argv[1], &atributos) == -1) { perror("Error en stat"); exit (-2); } if (atributos.st_mode & S_IFDIR) { fprintf(stdout, "Directorio = %s \n", argv[1]); obtener_entradas_directorio(argv[1]); } else { fprintf(stdout, "El argumento %s no es un directorio \n", argv[1]); exit(-3); } return 0; } void obtener_entradas_directorio (char *directorio) { DIR *dirp; struct dirent *direntp; struct stat atributos; int retorno; char ruta[LONGITUD_MAX]; dirp = opendir (directorio); if (dirp == NULL) { fprintf(stderr,"No se puede acceder al directorio %s\n", directorio); exit (-4); } // Obtenemos la primera entrada del directorio (ED) direntp = readdir(dirp); // Mientras haya entradas en el directorio while (direntp != NULL) { // Construimos la ruta sprintf(ruta, "%s/%s", directorio, direntp->d_name); // Obtenemos información de la ED actual retorno = stat(ruta, &atributos); if (retorno == -1) { fprintf(stderr, "Error en stat de %s \n", direntp->d_name); } else { // Si es un fichero regular y tiene permiso de ejecución, mostramos la ruta y el tamanno if (atributos.st_mode & S_IFREG) // if (S_ISREG (atributos.st_mode) ) { if(atributos.st_mode & S_IXUSR) 4 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 fprintf(stdout, "Ruta del archivo ejecutable = %s Tamanno = %d bytes \n", ruta, atributos.st_size); } // Si es un directorio seguimos por el subdirectorio siguiente else if (S_ISDIR (atributos.st_mode) && strcmp (direntp->d_name,".") != 0 && strcmp (direntp->d_name,"..") != 0) { obtener_entradas_directorio (ruta); } } // Obtenemos la siguiente ED direntp = readdir(dirp); } closedir(dirp); } 5 6 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 [Cuestión 3.]Se desea resolver en C, haciendo uso de la librería de semáforos vista en clase, el problema de los lectores/escritores, teniendo en cuenta los siguientes aspectos de sincronización: Existirán varios procesos escritores, cada uno de los cuales realizará como máximo diez escrituras en el fichero bd.txt; en caso de que exista el fichero, se añadirán por el final. Suponga que transcurre un segundo entre dos operaciones seguidas de escritura. Los lectores accederán concurrentemente a dicho fichero e irán leyendo las líneas de una en una; una vez leída una línea será borrada. No existe relación filial entre los lectores y los escritores. A continuación, se detallan el resto de consideraciones del ejercicio: Los elementos que se escribirán en el fichero tendrán el siguiente formato: “He escrito el elemento <i> (Proceso Escritor <PID>)”. Sólo un proceso, de cualquier tipo, puede estar accediendo al fichero en un determinado instante. Se instalará un manejador en el lector, asociado a la señal SIGINT, que será el encargado de destruir el/los semáforo/s y el fichero. Los prototipos de las funciones para el acceso al fichero son los siguientes: i. void Escribir_Linea (char *fichero, char* cadena).- Añade una línea con la cadena de caracteres al final del fichero. ii. void Leer_Linea (char *fichero).- Leerá y eliminará la primera línea del fichero, en caso de no estar vacío. Por tanto, debe implementar al menos dos programas, uno para para el lector y otro para el escritor. Sobre las funciones auxiliares, suponga ya definida la función Leer_Linea, por lo que necesitará codificar la función Escribir_Linea y el manejador asociado a la señal SIGINT. Puntuación: 3 ptos. #include #include #include #include #include #include #include Tiempo estimado: 40 min. <stdio.h> <sys/types.h> <sys/stat.h> <fcntl.h> <string.h> <errno.h> <signal.h> #include "Semaph.h" void Iniciador (); void Terminador (int sig); void Escribir_Linea(char *fichero, char* cadena); Semaph excmut, escritos; /*************************************************************/ // lector.c // /*************************************************************/ #include "funciones.h" int main() { Iniciador(); if (signal(SIGINT, Terminador)== SIG_ERR) perror ("Error al instalar el manejador asociado a SIGINT"); while(1) { Semaph_Down(escritos); 7 } } Semaph_Down(excmut); fprintf(stdout, "Voy a leer un valor\n"); Leer_Linea("bd.txt"); Semaph_Up(excmut); /*************************************************************/ // escritor.c // /*************************************************************/ #include "funciones.h" int main() { int i=0; char cadena[255]; Iniciador(); if (signal(SIGINT, Terminador)== SIG_ERR) perror ("Error al instalar el manejador asociado a SIGINT"); } for(i=0;i<10;i++) { Semaph_Down(excmut); sprintf(cadena, "He escrito el elemento %d (Proceso Escritor %ld)\n", i,getpid()); Escribir_Linea("bd.txt", cadena); Semaph_Up(excmut); Semaph_Up(escritos); // Entre dos operaciones de escritura el escritor // está ocioso un segundo. sleep(1); } /*************************************************************/ // funciones.c // /*************************************************************/ #include "funciones.h" void Iniciador () { excmut = Semaph_Create("excmut", 1); if (excmut == -1) { perror("Error al crear/acceder semaforo excmut"); exit(-1); } } escritos = Semaph_Create("escritos", 0); if (escritos == -1) { perror("Error al crear/acceder semaforo escritos"); exit(-1); } void Terminador (int sig) { Semaph_Destroy("excmut", excmut); Semaph_Destroy("escritos", escritos); unlink("bd.txt"); } void Escribir_Linea(char *fichero, char* cadena) { int fd; fd = open("bd.txt", O_CREAT | O_WRONLY | O_APPEND, 0600); 8 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 if (fd == -1) { perror("Error en open"); exit(-1); } // Escribe la cadena en el fichero if (write(fd, cadena, strlen(cadena)) == -1) { perror("Error en la escritura"); exit(-1); } fprintf(stdout, "%s \t escrito en datos.txt\n", cadena); fprintf(stdout, "--------------------------------------------\n"); } close(fd); 9 10 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 [Cuestión 4.]Realice un cliente en C que se conecte al puerto 2323 de un servidor que se indicará como primer argumento al invocar el programa. Además, el cliente tomará los siguientes argumentos como nombres de usuarios que hay que enviar al servidor en un determinado protocolo para que éste nos diga si existen en el sistema. La información recibida del servidor se mostrará por pantalla. NOTAS: - Si el usuario no pasa a nuestro cliente el número de argumentos adecuados, mostrará un mensaje de uso por pantalla. - La cadena que se debe enviar al servidor para comprobar si existe el usuario en dicho servidor es: USER usuario, reemplazando usuario por cada uno de los nombres que se han pasado como argumentos. El servidor contestará con OK si el usuario existe y con NOK en caso de que el usuario no exista en el servidor. Para terminar, debe enviarse el mensaje FIN al servidor y éste contestará también con dicho mensaje y se cerrará la conexión. - Implemente únicamente el cliente A continuación se muestra un ejemplo del funcionamiento del programa: $ ./usuarios murillo.eii.us.es juanpe fragu moreno Envío: USER juanpe Respuesta: OK Envío: USER fragu Respuesta: NOK Envío: USER moreno Respuesta: OK Envío: FIN Respuesta: FIN $ Figura 2. Ejemplo de funcionamiento del programa. Puntuación: 3 ptos. #include #include #include #include #include #include #include #include #include #include #include #include Tiempo estimado: 30 min. <stdio.h> <stdlib.h> <sys/socket.h> <sys/types.h> <netinet/in.h> <netdb.h> <string.h> <stdio.h> <arpa/inet.h> <errno.h> <sys/wait.h> <signal.h> #define LONG_HOSTNAME 100 #define TAM_MENSAJE 100 int main(int argc, char * argv[]) { int socket_escucha, puerto; int s; struct sockaddr_in sin; struct hostent *hp; char hostname[LONG_HOSTNAME]; char mensaje[TAM_MENSAJE]=""; char fichero[TAM_MENSAJE]; 11 int n_bytes=0,i; if (argc < 3) { fprintf(stderr, "Uso: %s <maquina> <usuario>...\n", argv[0]); exit(EXIT_FAILURE); } /* Almacenamos host */ sscanf(argv[1],"%s", hostname); n"); /* Obtenemos la direccion IP a partir del nombre */ hp = gethostbyname(hostname); if (hp == NULL) { perror("Error al obtener la direccion IP asociada al nombre de la maquina\ } exit(EXIT_FAILURE); /* Creamos el socket de escucha */ if ((s = socket(AF_INET, SOCK_STREAM,0))<0) { perror("Error al crear el socket"); exit(EXIT_FAILURE); } /* Creamos la direccion a la que enlazar el socket de escucha */ sin.sin_family = AF_INET; /* Tipo internet */ sin.sin_port = htons(2323); /* Puerto en Network byte order */ memmove(&sin.sin_addr, hp->h_addr, hp->h_length); /* Obtenemos la direccion IP de Network byte order */ if (connect(s, (struct sockaddr *) &sin, sizeof(sin))<0) { perror("Error al hacer accept"); exit(EXIT_FAILURE); } for(i=2;i<argc;i++) { sprintf(mensaje,"USER %s", argv[i]); printf("Envio: %s\n", mensaje); n_bytes=send(s,mensaje, strlen(mensaje),0); if (n_bytes < 0) { perror("Error en send"); exit(EXIT_FAILURE); } n_bytes=recv(s,mensaje, sizeof(mensaje),0); if (n_bytes > 0) { mensaje[n_bytes]='\0'; printf("Respuesta: %s\n", mensaje); fflush(stdout); } else { fprintf(stderr,"Error en recv\n"); exit(EXIT_FAILURE); } } //for argumentos sprintf(mensaje,"FIN"); printf("Envio: %s\n", mensaje); n_bytes=send(s,mensaje, strlen(mensaje),0); if (n_bytes < 0) { perror("Error en send"); exit(EXIT_FAILURE); 12 Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria Curso 2008/09. Tercero Ingeniería Informática Nombre: Apellidos: 17 de Junio de 2009 } { n_bytes=recv(s,mensaje, sizeof(mensaje),0); if (n_bytes > 0) } mensaje[n_bytes]='\0'; printf("Respuesta: %s\n", mensaje); fflush(stdout); close(s); } /*main*/ 13