Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.org

Funciones raras, pero útiles, de C en Unix/Linux

ALGUNAS FUNCIONES RARAS PERO UTILES DE C EN UNIX/LINUX

Aquí voy a poner algunas funciones poco conocidas de C para Unix/Linux, pero que pueden resultar útiles.

popen()

La función popen(), de stdio.h, permite "abrir" un ejecutable. Al abrilo, dicho ejecutable se ejecutará y popen() nos devolverá un descriptor de fichero FILE *. Si abrimos el ejecutable como de lectura, con el descriptor de fichero devuelto podremos leer la salida en pantalla del ejecutable.

Como ejemplo, vamos a abrir el ejecutable "/bin/ls", con lo que nuestro programa leerá el nombre de los ficheros contenidos en el directorio actual.

¡OJO!. Este popen("/bin/ls") es un ejemplo.
Si quieres saber qué ficheros hay en un directorio,
mejor usa las función scandir().
Es mucho más eficiente.

Los parámetros de FILE *popen(char *, char *) son:

Una vez abierto el fichero, nos devuelve un FILE *, que podremos leer con las funciones normales de C fscanf(), fgets(), etc. En nuestro ejemplo leeremos con fgets() hasta final de fichero (fin de la salida del ejecutable) e iremos escribiendo dichas líneas en pantalla.

Cuando se ha terminado de leer, se cierra el fichero con pclose().

En PruebaPopen.c tienes el código de ejemplo. Puedes descargarlo, quitarle la extensión .txt y compilarlo con make PruebaPopen (no hace falta Makefile) o bien con gcc PruebaPopen.c-o PruebaPopen. Si lo ejecutas, obtendrás la misma salida que un ls -l.

También como ejemplo, vamos a abrir more con popen() para escritura. El resultado es que todo lo que escribamos a través del descriptor de fichero devuelto por popen(), será tratado automáticamente por more, parándose la salida cuando completemos una página y esperando que el usuario pulse <intro> para continuar. Es una forma cómoda de paginar nuestras salidas por pantalla.

Los parámetros a pasar serán popen("more", "w").

Para escribir datos, usaremos fprintf ().

En PruebaPopen2.c tienes el código de ejemplo para abrir more como de escritura. Al igual que el ejemplo anterior, puedes compilar con make PruebaPopen2 o con gcc PruebaPopen2.c -o PruebaPopen.

Un pequeño incordio de esta función es que no puede abrirse simultáneamente como escritura y lectura, con lo que no nos permite abrir un ejecutable, pasarle datos y leer sus resultados.

Imprimir en C de linux

Conozco dos posibles formas de imprimir:

La primera forma de imprimir consiste en usar la función popen() para abrir el comando de imprmir lpr (linux) o lp (solaris) como de escritura. Una vez abierto, todo lo que escribamos en el descriptor de fichero devuelto por popen(), saldrá por la impresora.

Básicamente la secuencia de funciones de C sería

File *impresora = popen ("lpr", "w");
...
fprintf (impresora, "Linea a imprimir número %d\n", contadorLineas);
...
pclose (impresora);

Un pequeño ejemplo. Descarga Imprime.c, le quitas la extensión .txt, lo compilas con gcc Imprime.c -o Imprime o con make Imprime y lo ejecutas. Saldrán 10 líneas de texto por la impresora.

La segunda forma, que es la que utilizaba hasta ahora, es escribir el texto en un fichero cualquiera y luego, con la función de C system(), ejecutar un comando lpr (de linux) o lp (de solaris).

La secuencia de funciones en C sería más o menos

File *ficheroTemporal = fopen ("/tmp/ParaImprimir", "w");
...
fprintf (ficheroTemporal, "Linea a imprimir número %d\n", contadorLineas);
...
fclose (ficheroTemporal);
...
system ("lpr /tmp/ParaImprimir");

Podemos incluso poner a lpr todas las opciones que queramos de impresión, concatenar con pr para que salga una "impresión" bonita, etc.

No conozco ninguna forma "directa" de imprimir en C de linux. Si alguien sabe de alguna mejor, que me la cuente a chuidiang@gmail.com.

lstat()

La función lstat() y sus amigas fstat() y stat() permiten obtener información de un fichero: propietario, tamaño, permisos, tipo de fichero, etc.

    La función lstat() admite dos parámetros: Devuelve -1 si hay algún error, como por ejemplo, que el fichero no exista.

La struct stat debemos crearla antes de llamar a la función lstat() y pasarle un puntero a dicha estructura. La función nos la rellenará y luego podremos mirar sus campos. Esta estructura tiene un montón de campos para ver propietario, tamaño, permisos, etc, etc. Si echas un ojo al man de lstat() podrás ver todo lo que tiene.

struct stat datosFichero;
...
lstat ("fichero", &datosFichero);

El campo que nos indica el tipo de fichero (entre otras cosas), es st_mode. Tenemos varias macros disponibles para saber el tipo de fichero.

Hay más macros para saber si el fichero es un dispositivo de caracteres, de bloques, un socket, etc. Te dejo que le eches un ojo al man para que te lo cuente.

En Plstat.c tienes un ejemplo. Lo descargas, le quitas el .txt, lo compilas con make Plstat o con gcc Plstat.c -o Plstat y lo ejecutas. El programa crea un directorio, un fichero, un link, un link simbólico y los comprueba con la función lstat(). Luego borra lo que ha creado.

scandir()

Para poder ver qué ficheros tienes en un directorio desde un programa C, tienes la función scandir().

La función scandir() admite cuatro parámetros. Son un poco liados, así que si quieres ir al grano, vete unas líneas más abajo al código de ejemplo y verás la forma fácil de usar esta función. Los parámetros son:

Resumiendo y de la forma más fácil, basta con llamar a la función de la siguiente manera

sstruct dirent **resultados = NULL;
int numeroResultados;
...
numeroResultados = scandir ("directorio", &resultados, NULL, NULL);

    La función devuelve el número de ficheros que nos ha dejado en resultados o -1 si ha habido error. Crea además memoria para resultados y en ella los mete.

    La estructura struct dirent tiene muchos campos dentro con información diversa. El nombre del fichero está en un campo denominado d_name. Para acceder a ellos el código es

    int i;
    ...
    for (i=0; i<numeroResultados; i++)
        printf ("Nombre fichero %s\n", resultados[i]->d_name);

    Como podemos comprobar en el código anterior, nuestra variable resultados la inicializamos a NULL. La función scandir() le reserva memoria con malloc(). Cuando no necesitemos esos resultados, debemos liberarlos con free(). Debemos liberar por un lado cada uno de los punteros/elementos del array y finalmente, el array en sí mismo. El código para ello sería

int i;
...
for (i=0; i<numeroResultados; i++)
{
     free (resultados[i]);
     resultados[i] = NULL;
}
free(resultados);
resultados = NULL;

En Mils.c tienes un código de ejemplo que saca una lista de los ficheros en un directorio. Lo puedes descargar, quitarle la extensión .txt, compilarlo con make Mils o con gcc Mils.c -o Mils y lo ejecutas. Te saldrán en pantalla los ficheros que tengas en el directorio donde has ejecutado el programa.

Un buen libro de programación en C sobre Unix.

 

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: