En esta primera práctica nos familiarizaremos con el uso de las máquinas del laboratorio y de las herramientas de programación necesarias para realizar las siguientes prácticas. Las prácticas de esta asignatura se programarán en C sobre una distribución de Linux y se utilizará git como herramienta de control de versiones.
Los sistemas UNIX son multiusuario, permitiendo que el mismo equipo sea usado por varios usuarios (incluso al mismo tiempo). Los usuarios pueden utilizar el ordenador tanto de forma local (estando sentados delante) como de forma remota (dándole órdenes a través de la red desde otro ordenador como se verá luego). Normalmente los propietarios de ordenadores UNIX no quieren que cualquiera pueda utilizar su ordenador así que es necesario que el sistema operativo UNIX almacene los datos de los usuarios que tienen derecho a usarlo. A esto se le llama cuenta. La cuenta se identifica por un nombre y una contraseña que se supone que sólo es conocida por el usuario autorizado y que le permite probar su identidad.
Cada cuenta permite a su usuario utilizar una máquina UNIX a la que se le han dado ciertos privilegios, pudiendo acceder sólo a los ficheros que sean propiedad de ese usuario y utilizando las aplicaciones que se permitan a ese usuario. Hay una cuenta especial en las máquinas UNIX, y es la cuenta del administrador del sistema. Esta cuenta se llama normalmente root y no tiene ninguna limitación de permisos, es decir, puede realizar cualquier acción en el sistema y tiene acceso a todos los ficheros, de cualquiera de los usuarios.
Al proceso de identificarse en el sistema mediante el nombre de cuenta y contraseña antes de utilizar el sistema lo llamaremos hacer login.
El primer paso, por tanto, para usar un sistema UNIX es conseguir una cuenta. Para eso tenéis que apuntaros en la página que se pasará en clase y elegir grupo de prácticas y número de cuenta.
A cada pareja de alumnos se le ha asignado una cuenta que le permite utilizar cualquiera de los PCs de propósito general del laboratorio. Esta cuenta se llamará rc<numero>, el profesor comunicará la contraseña en clase.
Antes de probar a utilizar más aplicaciones debes cambiar la contraseña asignada. De esta forma, únicamente vosotros podréis acceder a esta cuenta. Para ello sigue las instrucciones:
Busca una aplicación de terminal (también llamada de consola) que te permita ejecutar comandos en el sistema operativo.
Elije una contraseña nueva que proteja vuestra cuenta. Una buena contraseña debe ser suficientemente larga y suficientemente difícil de averiguar. Los consejos típicos son, que no se usen palabras que estén en el diccionario, y para eso se recomienda normalmente usar letras mayúsculas y minúsculas mezcladas con números y símbolos (&%$…). También es bueno que sea fácil de recordar para sus propietarios para evitar escribirla en un papel, si no está escrita nadie la puede ver. Usa el sentido común y pensar una contraseña para vuestra cuenta.
Utiliza el comando passwd, para cambiar la contraseña de vuestra cuenta en la red de Telemática.
$ passwd
Identity validation...
enter your UNIX password:
Changing UNIX and samba passwords for rc71 New password:
Retype new password:
$
Si el programa no indica ningún error es que la contraseña ha sido cambiada correctamente. En caso de que no haya sido así, averiguar y descubrir el por qué y cambiarla correctamente. Ten en cuenta que puede fallar si no pones bien la contraseña actual o si no escribes la misma nueva contraseña dos veces. También es posible que el comando “se queje” Si se intenta poner una contraseña demasiado fácil.
Prueba a salir de la cuenta (logout) y vuelve a entrar para comprobar que la contraseña original ya no funciona y la nueva contraseña funciona.
Asegúrate que vuestra cuenta tiene una nueva contraseña antes de continuar. Ten en cuenta que tener los ordenadores con contraseñas conocidas es un problema grave de seguridad, así que las cuentas que sigan teniendo la misma contraseña se considerará que no tienen propietario y serán eliminadas.
Como has visto, sólo tienes que poner tu cuenta y tu contraseña y entrarás al sistema en modo gráfico. En breves instantes tendrá́s el escritorio de Linux. El sistema gráfico de UNIX se llama X (o X-Window o X11) que es el motor que dibuja en pantalla. Supondremos que ya tienes experiencia en moverte por un escritorio gráfico con un ratón, así que experimenta por tu cuenta. Pero debes buscar y aprender a hacer al menos las siguientes cosas:
Ya has probado como lanzar un terminal. Un terminal es una aplicación que te permite abrir una sesión de comandos. El terminal lanza un programa llamado shell que te permite escribir comandos o lanzar programas. Una vez que consigas esto, puedes escribir los comandos que ya conoces y muchos otros que aprenderás. Aunque vayas a usar las X en la mayoría de las prácticas necesitarás seguir escribiendo comandos.
Localiza, si no lo has hecho ya, un navegador de web.
Busca un editor de texto, los clásicos son vi o emacs pero quizás te parezcan que tienen un aspecto anticuado, siguen siendo útiles porque pueden usarse en un interfaz de texto sin gráficos, normalmente en accesos remotos. Si prefieres algo más fácil, hay cientos de editores donde probar. Busca por ejemplo gedit o kate. Elije el que más te guste.
En cualquier caso, puedes lanzar los editores desde el terminal, lo que es útil si estás escribiendo comandos y quieres abrir un fichero desde el propio terminal. Para ello sólo tienes que escribir el nombre del editor seguido del fichero:
$ gedit nombrefichero
$ gedit nombrefichero &
Cuando has hecho login con tu cuenta en el ordenador en el que te encuentras, has tenido que indicar tu nombre de usuario y contraseña. Este es el proceso más sencillo de autentificación de usuarios en el que se tiene una lista de usuarios que pueden acceder al sistema con su correspondiente clave.
Todos los ordenadores del laboratorio tienen instalaciones independientes de Linux, es decir, cada uno de ellos funciona de forma independiente, pero todos ellos comparten los usuarios que pueden hacer login. De esta forma, uses el ordenador que uses, podrás acceder a tu cuenta con independencia. Todos los ordenadores del laboratorio estan compartiendo por red un mismo disco y sistema de ficheros por lo que aunque sean ordenadores los usuarios tienen un directorio home comun en todos los ordenadores. Puedes probar que si escribes un fichero en tu directorio y entras con ese mismo usuario en otro ordenador, el fichero esta en los dos. Eso solo ocurre con algunos directorios. El home de los usuarios es compartido pero el resto de directorios es local.
Para utilizar otro ordenador no es necesario estar sentado delante. Puedes acceder a controlar otro ordenador remotamente con herramientas como ssh. Cuando quieres acceder desde tu ordenador a otro ordenador, necesitas conocer su dirección IP (o su nombre DNS equivalente si lo tiene). Pregunta a otro compañero cuál es la dirección IP de su ordenador y ejecuta el siguiente comando:
ssh -l <user> <ip>
o
ssh <user>@<ip>
o
ssh <ip>
dónde:
Si lo has hecho bien, el comando ssh (Secure SHell) te pedirá tu contraseña (ejemplo del usuario rc50):
$ ssh rc50@10.0.1.120
rc50@10.0.1.120’s password:
$
Y cuando la teclees correctamente, estarás de nuevo en tu cuenta (verás que tienes los mismos ficheros porque el directorio es compartido), pero físicamente estarás en el otro ordenador.
De esta forma, puedes acceder a otros ordenadores, pero recuerda siempre salir de la sesión tecleando exit.
Además de autenticación con nombre de usuario y contraseña, SSH permite autenticarse utilizando un par de claves, una privada y otra pública. Este método es más seguro y conveniente, ya que elimina la necesidad de entrar la contraseña cada vez que te conectas a un servidor.
Para configurar la autenticación mediante claves SSH utiliza el comando ssh-keygen para generar un par de claves pública y privada.
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/mikel/.ssh/id_rsa):
Acepta la opción por defecto con enter para que se genere con el nombre por defecto (que es ~/.ssh/id_rsa)
- Tu clave pública se generará en ~/.ssh/id_rsa.pub
- Tu clave privada se generará en ~/.ssh/id_rsa`
Después de generar las claves, copia la clave pública al archivo .ssh/authorized_keys de la máquina remota (que en nuestro caso como las maquinas comparten home vale con hacerlo en la misma máquina). Una vez copiado puedes intentar entrar en la máquina remota con
$ ssh <ip>
Esta vez, no debería solicitarte una contraseña, ya que la autenticación se realiza mediante las claves. Recuerda que la clave privada debe almacenarse de forma segura, ya que proporciona acceso a tu cuenta. Nunca compartas tu clave privada. En esencia debes tratar esta clave privada como una contraseña. Puedes ponerla en otra maquina si quieres, por ejemplo en tu casa o en tu portatil. O tambien se puede generar diferentes claves privadas en diferentes máquinas y en el fichero authorized_keys poner varias claves publicas autorizadas.
Estas claves pueden usarse para usar el ssh de forma más comoda y se utilizan normalmente en los sistemas control de versiones como git
Referencia ssh : sobre ssh y acceso con claves privadas
git es un programa que permite hacer un seguimiento de los cambios que se han producido en el código de un proyecto. Permite mantener un proyecto de forma distribuida y editarse por diferentes personas. Existen otras alternativas más antiguas como RCS, CVS o Subversion, e incluso alguno muy similar como Mercurial o Bazaar pero git es uno de los mas usados. Estos softwares se denominan Distributed Version Control System (DVCS por sus siglas en inglés)
Como se trata de programar un proyecto entre un grupo de autores lo primero es establecer quién eres para que pueda etiquetar los cambios, para ello ejecutaremos estos dos comandos (tienes que cambiar lo que va entre comillas):
$ git config --global user.name "Tu nombre"
$ git config --global user.email "email@example.com"
Un proyecto en git lo llamaremos repositorio y contiene toda la historia de cambios del proyecto en curso, no solo la ultima versión. Se puede construir un repositorio en su ordenador y sincronizar varios repositorios haciendo que los cambios en uno se hagan en el otro pero la forma más tipica de uso es que construiremos un repositorio en un servidor en la nube y los contribuyentes a ese proyecto tendran copias locales.
En cada copia local se pueden hacer cambios en el programa y las operaciones basicas son declarar un cambio como oficial con lo que pasara a formar parte de la historia (commit) enviar la historia oficial hacie el repositorio de la nube (push) y traer los cambios que pueda haber nuevos en el servidor de la nube (pull) por ejemplo si otros contribuyentes han cambiado alguna parte del proyecto.
El uso avanzado de git incluye más operaciones pero para una introducción con estas son suficientes.
Las prácticas de la asignatura se entregaran utilizando git. A cada grupo se le asignara un repositorio en bitbucket.org y la última version subida a dicho repositorio se considerará la entrega. Para ello necesita hacer una cuenta en bitbucket.org. Cree una si no la ha creado ya y comunique al profesor su cuenta para que le asigne el repositorio a su grupo. Una vez que tenga cuenta con repositorio asociado puede seguir la práctica.
Las operaciones de git con el servidor en la nube se hacen a traves de ssh. Si estas operaciones se autentican con contraseña tendríamos que entrar la contraseña cada dos por tres y es muy incomodo. Para funcionar de forma rápida git usará ssh con claves privadas como hemos visto antes. Para que funcione correctamente debera configurar en su cuenta de bibtbucket la clave id_rsa.pub que utiliza en el ordenador desde el que accede para que autorice las operaciones. De esta forma no le preguntara contraseña en cada operación. Puede usar la misma clave id_rsa en varios ordenadores o generar una en cada uno y registrar varias en bitbucket. Recuerde que debe mantener id_rsa secreta y a salvo pero no pasa nada por decirle a bitbucket o a cualquiera el contenido de id_rsa.pub.
Registre una clave ssh en bitbucket para seguir. Tenga cuidado porque en bitbucket se pueden registrar claves asociadas a repositorios o proyectos para permitir a alguien descargar ese proyecto. Pero lo que necesita es poder enviar cosas a todos los proyectos de su cuenta para eso debe registrar una clave ssh en sus preferencias personales. Con eso la clave le permitira acceder y enviar cambios a todos sus repositorios. Asi que vaya a
bitbucket >> personal bitbucket settings >> security > SSH keys > add key
Y registrela ahi. Cuidado que hay otros add key en otras secciones
Si te interesa saber mas de como funciona puedes aprender más sobre el tema en esta página de la wikipedia http://es.wikipedia.org/wiki/Criptografía_asimétrica. Puedes ver cómo hacer todo el proceso explicado de forma detallada en esta web (https://confluence.atlassian.com/bitbucket/set-up-ssh-for-git-728138079.html)
A generar una copia local a partir del repositorio en la nube le llamamamos clonar el repositorio. Clone su sepositorio en el ordenador del laboratorio usando git (cambiando p1equipo55 por su repositorio claro)
$ cd
$ git clone git@bitbucket.org:rcpracticas2/p1equipo55.git
cd p1equipo55
Ahora puede ver y editar su copia local del proyecto que esta en el directorio p1equipo55 si lo necesita puede hacer otras copias locales en este u otros ordenadores, por ejemplo cada miembro del grupo puede tener el suyo, o puede mantener una copia local en casa, lo importante es saber distinguir que cambios son locales y solo existen en una copia local y que cambios han sido subidos a la historia oficial del repositorio.
Ahora mismo su repositorio esta practicamente vacio. Puede ver que en la pagina del repositorio en github no hay nada y que en el direcotorio de la copia local no hay nada (salvo un directorio oculto .git que es donde se mantiene la historia de todos los cambios)
Veamos como hacer cambios y subirlos al repositorio.
Cree un archivo en su directorio que se llame README.md con cualquier editor. Si el repositorio ya tenia uno editelo y cambie algo. Escriba el nombre de los miembros de este grupo con el formato que se muestra, para que el profesor vea a quien pertenece. Una vez grabados los cambios los cambios estan en el fichero local. Comrpuebe en la pagina de bitbucket que el repositorio oficial no tiene los cambios. Haga el siguiente comando en su copia local.
En README.md debe aparecer la información de los autores con el siguiente formato, algo asi:
Autores:
* 33123 SMITH, Jhon
* 00001 ANDERSON, Neo
$ git status
Git le indicara que hay cambios locales que no se la indicado si son oficiales o no. Ahora mismo los cambios estan en un fichero unicamente el README.md si hubiera cambiado mas ficheros le mostraría cuales. Para indicar a git que quermos elegir unos cambios que enviar debe usar el comando git add.
$ git add README.md
$ git status
Vera que ahora el status es que los cambios estan preparados para aceptarse (en verde). Si hay varios ficheros con cambios puede añadirlos independientemente cada uno con un git add. Cuando ha hecho una serie de cambios puede elegir enviar algunos ficheros y otros no. Esa es la idea del git add. Tambien hay comandos para para cancelar el efecto de add y quitar el fichero con git restore o para añadir el cambio de borrar un archivo que ya existia git rm pero de momento aprenda los basicos.
El comando git add prepara los cambios para añadirlos a la historia pero aun no han sido añadidos. Observe que si hace el comando
$ git log
Los cambios no aparecen y que si mira el repositorio en la pagina de bitbucket.org no ha cambiado nada. Para hacer oficiales los cambios debe hacer el siguiente comando que añadira a la historia todos los cambios preparados con git add. Se suele indicar un comentario con -m indicando que cambios se han hecho.
$ git commit -m 'Primer commit'
Al hacer eso los cambios se añadiran a la historia oficial de esta copia local. Puede comprobarlo haciendo el comando
$ git log
Ahora la historia tiene un commit. Puede hacer mas cambios y ver como se añaden nuevas lineas a la historia. Pero si mira en la pagina de bitbucket vera que estos cambios solo estan aun en su ordenador. La historia esta solo en la copia local. Para enviar la historia al servidor debe hacer
$ git push
Observa que ahora en la página de bitbucket estan los cambios. Ahora otros usuarios del grupo y los profesores pueden ver los cambios. Por ejemplo utilice una copia local en otro ordenador u otro directorio para ver que puede traer los cambios
cd
git clone repositiorio otrodirectorio
La copia que se bajará ya incluye la nueva historioa. Compruebelo con git log
Haga algun cambio en una de las copias y añada el cambio a la historia con el ciclo
$ git add README.md
$ git commit -m 'cambiado algo'
$ git push
Ahora los cambios estan en la copia en la que los ha hecho y en la pagina de bitbucket
Para obtener los ultimos cambios en el otro ordenador debe hacer
$ git log
# observe que no estan
$ git pull
$ git log
# observe la nueva version
Esta es la idea de git. Varios programadores pueden manejar un mismo proyecto haciendo cambios sobre el mismo. Pero la historia de cambios oficial solo puede ser una. No es problema que mientras este cambiando el programa otra persona haya enviado sus propios cambios. Normalmente cuando sabe que hay otros cambios debe hacer git pull para traerlos. Antes de enviar cambios deberia hacer algo asi
$ git pull
# traer cambios pendientes que pueda haber y resolver los conflictos
$ git add xxxx
$ git add yyy
# añadir los ficheros que ha cambiado
$ git commit -m 'descripcion'
# añadir los cambios a esta historia
$ git push
# subir la historia
Con eso y un poco de comunicacion se puede mantener el proyecto facilmente. Si ocurren conflictos puede modificarse la historia local y hay opoeraciones un poco mas complicadas pero se salen del contenido de esta asignatura de introducción. Recuerde que ante un conflicto grave siempre puede abandonar una copia local, clonar una nueva y pone en esa los cambios que esten pendientes y seguir con la historia oficial.
Referencia git : sobre git
make
A continuación nos familiarizaremos con las herramientas de programación en Linux, el uso de gcc y make. En el proceso se practicará con la programación en C en un sistema operativo UNIX, en especial la programación de herramientas de línea de comando que utilicen argumentos.
En primer lugar escribe un programa en C sencillo que muestre algo en pantalla y guárdalo en un fichero llamado programa.c
Ejemplo de programa.c
#include <stdio.h>
int main() {
printf("primer programa de RC... \n");
return 0;
}
Para compilar el programa en C utiliza el comando gcc que incluye las funciones de compilador y de linker. Haciendo:
$ gcc programa.c -o programa
Se le indica al compilador que compile el programa que hay en el código fuente `programa.c, que lo enlace con las librerías necesarias y que si todo funciona correctamente, construya (salida “-o” output) un ejecutable llamado programa que se encontrará en el mismo directorio. Puedes ejecutar este programa lanzándolo desde el terminal:
$ ./programa
primer programa de RC...
$
Pero normalmente utilizaremos el comando make para ayudarnos a organizar las fuentes de un programa y a compilarlo con una sola instrucción. Para ello hay que colocar un fichero con nombre Makefile (o también vale en minúsculas makefile) en el mismo directorio que las fuentes del programa. El fichero Makefile contiene los comandos necesarios para compilar el programa.
Veamos por ejemplo cómo compilar el programa anterior con make. Todas las prácticas que hay que presentar en esta asignatura deberán tener un Makefile que construya el programa sin errores, ni advertencias (warnings).
Haz un directorio para el programa de ejemplo y coloca en ese directorio el fichero con las fuentes programa.c anterior. Construye un fichero Makefile con el siguiente contenido:
Ejemplo de Makefile:
# En los ficheros makefile puede haber comentarios
# los comentarios se ponen con líneas que empiezan por #
compilar: programa.c
gcc programa.c -o programa
Es muy importante tener en cuenta que la indentación del fichero Makefile se realiza con tabuladores y no con espacios. Usar el more en línea de comandos para que no se cuele ningún carácter extraño.
Con el fichero Makefile anterior y el fichero programa.c en el mismo directorio puedes construir el programa ejecutable con solo ir a ese directorio y hacer make. Obtendrás algo parecido a esto:
$ ls
Makefile programa.c
$ make
gcc programa.c -o programa
$ ls
Makefile programa programa.c
$
Puede verse que el comando make ha leído del fichero Makefile cómo compilar el programa y ha realizado la tarea, obteniendo el ejecutable programa. Puede parecer que no es una gran ganancia escribir sólo make en lugar de escribir el comando gcc completo, pero conforme los programas van haciéndose más complejos la construcción incluirá́ compilar varios módulos y unir los módulos entre sí o con librerías externas para generar uno o varios ejecutables. make nos permite automatizar todas estas funciones para compilar con órdenes simples.
En el Makefile básicamente se indica cómo construir unos ficheros a partir de otros.
Tomando de nuevo el ejemplo anterior:
compilar: programa.c
gcc programa.c -o programa
Lo que define este Makefile es un objetivo. Cada objetivo se divide en tres partes:
Etiqueta o nombre: texto al inicio de la línea seguido de dos puntos. Identifica la tarea que se va a realizar. En este caso compilar.
Dependencias: lista de ficheros (separadas por espacios) necesarios para que el comando funcione correctamente. En este caso programa.c.
Comandos: cada uno de los comandos a ejecutar, todos ellos indentados con un tabulador y sin líneas en blanco entre ellos. En este caso, el comando gcc con sus parámetros.
Pueden indicarse tantos objetivos como queramos. Cada uno tiene que tener un nombre distinto.
Resumiendo, el objetivo llamado compilar indica que para construir el fichero programa a partir de programa.c hay que ejecutar una sola línea que es el gcc. El make ejecuta la línea si ve que el fichero programa.c ha sido modificado más recientemente que programa. Puedes observar que si ejecutas make varias veces seguidas, a la segunda (y posteriores) indicará que el programa ya está compilado y no hará nada.
Podemos forzar que vuelva a compilar borrando el programa ejecutable o realizando cualquier cambio en el fichero fuente de forma que sea más nuevo que el ejecutable. También existe el comando touch que actualiza la fecha de modificación de un fichero como si hubiera sufrido un cambio. Puedes hacer touch programa.c lo que provocará que make crea que el fichero ha sido modificado y recompile.
Al hacer make se intenta construir el primer objetivo que haya en el Makefile. El Makefile puede contener varias descripciones de dependencias. Normalmente sólo se construye la primera, pero se le puede indicar a make que dependencia queremos construir en la línea de comandos
Ejemplo:
# para construir la primera dependencia
$ make
# para construir una dependencia concreta
$ make programa
$ make programa2
También se pueden hacer que las dependencias no construyan un fichero concreto sino que sean simples claves para decirle a make que construir. Y también puede ser que los ficheros de los que dependa una clave, dependan a su vez de otros ficheros. En ese caso make resolverá todas las dependencias necesarias hasta que pueda construir el programa. Prueba por ejemplo este Makefile:
Ejemplo de otro Makefile más complicado:
# Makefile
programa: programa.c
echo "Compilando el programa programa.c"
gcc programa.c -o programa
programa2: programa2.c
echo "Compilando el programa programa2.c"
gcc programa2.c -o programa2
todos: programa programa2
Para ello, escribe un programa en el fichero programa2.c y prueba que hace el Makefile anterior. Si ahora ejecutamos los siguientes comandos:
$ make programa
$ make programa2
$ make todos
$ make
¿Cómo harías que se construyan todos los programas al hacer un único make?
Como has visto ya puedes programar herramientas que sean comandos de UNIX. En las siguientes prácticas programaremos comandos que permitan utilizar la red. La mayoría de los comandos necesitarán argumentos de entrada para indicarles diferentes opciones.
Escribe el programa de ejemplo y comprueba su funcionamiento:
Fichero argumentos.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int i;
printf("Hay %d argumentos \n", argc);
for(i=0; i<argc; i++) {
printf("El argumento %d es: %s\n",i,argv[i]);
}
return 0;
}
Compila el programa y prueba los resultados con los siguientes ejemplos:
$ ./argumentos 1 dos 3 4 -5
$ ./argumentos cuantos argumentos "hay aquí"
$ ./argumentos
$ ./argumentos –a
Como puedes ver, en UNIX la función main recibe dos argumentos. El primero argc es un entero que indica cuántos elementos tiene el segundo. El segundo argv es un array de punteros a char. Cada puntero apunta a una cadena con uno de los argumentos. El primer argumento argv[0] no es un argumento, es el nombre del comando. Se puede utilizar para saber en qué directorio está el programa que se ha lanzado pero, en general, lo ignoraremos. El resto de elementos desde argv[1] hasta argv[argc-1] son las cadenas de texto que venían después del comando.
Así que, si el dato que queremos leer es una cadena, es fácil de extraer de los argumentos. Por ejemplo, en el siguiente programa se comprueba que hay al menos un primer argumento y se utiliza ese argumento como nombre de fichero para escribir los demás argumentos en ese fichero en lugar de en la pantalla. Ejemplo de programa que usa un argumento tipo cadena de texto:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int i;
char *filename;
FILE *f;
if(argc < 2) {
exit(0);
}
filename = argv[1];
f = fopen(filename,"w");
if(f == NULL) {
printf("No puedo abrir el fichero %s\n",argv[1]);
}
fprintf(f, "Has escrito %d argumentos \n", argc);
for (i=0; i<argc; i++) {
fprintf(f, "El argumento %d es: %s\n", i, argv[i]);
}
return 0;
}
Sin embargo, a veces querrás utilizar argumentos numéricos. Por ejemplo haciendo:
$ repite 3 hola
hola
hola
hola
$
En la variable argv[1] el contenido apuntará a la cadena “3” y no a un entero con el valor 3. Debes obtener la variable entera haciendo que C convierta o que lea la cadena. Para eso quizás hayas usado la función atoi() y similares (atoi(“3”) (Array TO Integer) devuelve el entero 3). Pero es más cómodo usar la función sscanf() (String SCANF). Se usa como scanf() pero para extraer datos de una cadena. sscanf(“3”,”%d”,&n) intenta leer la cadena “3” como si fuera un entero por usar el %d y pone el resultado en la variable n.
Prueba como ejercicio a construir el programa repite. Que funcione como el del ejemplo anterior. Es decir, que cumpla la siguiente especificación:
FORMATO
repite <n> <cadena>
DESCRIPCIÓN
Escribe por pantalla <cadena> tantas veces como se indique en el entero <n>
Frecuentemente, en las prácticas de red necesitaremos leer líneas escritas por teclado por el usuario. Para ello lo más recomendable es usar la función fgets(). Lee su funcionamiento usando man fgets. La función fgets(buf, n, f) lee la siguiente línea disponible en el fichero indicado por f y la coloca en la zona de memoria indicada por buf. La zona de memoria habrá sido construida con un array o un malloc y tendrá un tamaño finito por lo que se le indica en n el máximo tamaño que puede tener la línea.
Recuerda que en todos los lugares donde debas usar FILE* puedes utilizar stdin para indicar la entrada de texto y stdout para enviar la salida a la pantalla.
Prueba por ejemplo el siguiente programa que va leyendo líneas de texto del teclado y guardándolas en un fichero.
Ejemplo de programa que lee del teclado:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int i;
char *filename;
FILE *f;
char buf[256];
if(argc < 2) {
filename = "out";
}
else {
filename = argv[1];
}
f = fopen(filename, "w");
if(f == NULL) {
printf("No puedo abrir el fichero %s\n", argv[1]);
}
printf("> ");
while(fgets(buf, 255, stdin) != NULL) {
fprintf(f, "%s", buf);
printf("> ");
}
fclose(f);
return 0;
}
Para detener el programa hacer Ctr+D.
Acontinuació escribe un programa que cumpla la siguiente especificación:
FORMATO
escribe <nombre_del_fichero> <n>
DESCRIPCIÓN
<n> debe ser un número entero mayor que cero. El programa lo comprueba y en caso de que no lo sea, termina dando el error.
El programa debe quedarse esperando una línea de la entrada de teclado. Una vez leída, la escribirá en el fichero dado por <nombre_de_fichero> tantas veces como indique <n>, numerando las líneas en el proceso.
Ejemplo:
$ ./escribe out 4
hola
$ cat out
1: hola
2: hola
3: hola
4: hola
$
A lo largo de los distintos ejemplos de esta práctica se han visto los conceptos de programación de comandos UNIX que necesitaremos para programar las prácticas con la red pero que no son estrictamente programación de redes. Puedes utilizar estos ejemplos como base cuando realices programas que deban leer parámetros o utilizar la entrada de teclado.
Para completar esta practica debe subir los siguientes ficheros al repositorio
El fichero practica1/README.md con los nombres de los autores.
Un fichero practica1/makefile
que permita construir un binario repite que cumpla la especificación.
que permita construir un binario escribe que cumpla la especificación.