CUESTIÓN
Al ejecutar make
sobre la práctica de esta
sesión, ocurre lo siguiente:
/usuarios/gyermo/PRIVADO/SO/PRACTS/SESION1$ make
c89 -c sesion1.c
cc: "sesion1.c", line 5: error 1588: "UID_NO_CHANGE" undefined.
*** Error exit code 1
Stop.
PRIMERA APROXIMACIÓN
El error nos los está dando el compilador (cc
). El error
está localizado en el fichero sesion1.c
, en su línea
quinta. Nos dice que UID_NO_CHANGE
no está definido.
Si leemos la página de manual de chown
y similares, nos
dice:
RESUMEN
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
int fchown(int fildes, uid_t owner, gid_t group);
DESCRIPCIÓN
La llamada al sistema chown() cambia la pertenencia a un usuario y a
un grupo de un fichero. La variable path apunta al nombre de la ruta
de acceso del fichero. chown() asigna al ID de propietario y al ID de
grupo del fichero los valores numéricos contenidos en las variables
owner y group respectivamente. El valor de UID_NO_CHANGE o
GID_NO_CHANGE puede especificarse en owner o group para dejar
inalterado el ID de propietario o el ID de grupo del fichero,
[...]
En principio, no tenía por qué dar este error. UID_NO_CHANGE
,
al estar todo en mayúsculas, tiene toda la pinta de ser una macro.
Las macros suelen estar definidas en los ficheros de cabecera. De estar
definida en algún sitio, será en el fichero de cabecera correspondiente
a la función que estamos usando: unistd.h
.
Los ficheros de cabecera que se referencian en un fichero en C entre
signos de menor (<) y mayor (>), se encuentran dentro del
directorio /usr/include
. Miremos, pues, el contenido del
fichero /usr/include/unistd.h
:
/* @(#) $Revision: ../hdr/unistd.h@@/main/r11ros/0 $ */
#ifndef _UNISTD_INCLUDED
#define _UNISTD_INCLUDED
/*
* Unistd.h
* symbolic constants and structures which are used
* for support of the /usr/group standard.
*/
#include <sys/unistd.h>
#endif /* _UNISTD_INCLUDED */
El fichero primero comprueba que no ha sido incluído antes para, de ser
este el caso, no volverse a incluir. Esto es muy típico de los ficheros
de cabecera del sistema. Si no ha sido incluído antes, incluye el fichero
situado en /usr/include/sys/unistd.h
. Vamos a ver si este
fichero contiene la definición de la macro:
/usr/include/sys$ grep UID_NO_CHANGE unistd.h
/usr/include/sys$
Mala suerte. Busquemos en todos los ficheros de cabecera debajo del
subdirectorio /usr/include
, a ver si alguno contiene la
definición de la macro:
/usr/include$ find . -name "*.h" -exec grep UID_NO_CHANGE '{}' \; -print
#define VX_AT_ISUID(vap) ((vap)->va_uid != UID_NO_CHANGE)
./sys/fs/vx_hpux.h
# define UID_NO_CHANGE ((uid_t) -1) /* for chown(2) and setresuid(2) */
./sys/types.h
( N != UID_NO_CHANGE && N != O )
./sys/vnode.h
Parece que la definición de la macro, que además es -1, está en el fichero
/usr/include/sys/types.h
. Probablemente este fichero sea
incluído desde /usr/include/sys/unistd.h
. En ese fichero,
encontramos la definición de la macro:
[...]
#ifdef _INCLUDE_HPUX_SOURCE
typedef unsigned char u_char; /* Try to avoid using these */
typedef unsigned short u_short; /* Try to avoid using these */
typedef unsigned int u_int; /* Try to avoid using these */
[...]
/* These probably should be moved to some other header */
# define UID_NO_CHANGE ((uid_t) -1) /* for chown(2) and setresuid(2) */
# define GID_NO_CHANGE ((gid_t) -1) /* for chown(2) and setresgid(2) */
[...]
# endif /* __cplusplus */
# endif /* not _KERNEL */
#endif /* _INCLUDE_HPUX_SOURCE */
[...]
Nos damos cuenta inmediatamente que tiene que estar definida la macro
_INCLUDE_POSIX_SOURCE
para que pueda estar definida la
que nos está dando el error. Por lo tanto, bastará con que añadamos al
programa que estamos haciendo antes de los #include
la
definición de esta macro para que las cosas funcionen: #define
_INCLUDE_HPUX_SOURCE
. ¿Afectará esto al comportamiento del
programa cuando le llevemos a LINUX?
SOLUCIÓN
¿Tendremos que estar haciendo esto cada vez que no encuentre una macro
o la cabecera de una función? Esperemos que no. Podemos seguir
investigando un poco. Si le pedimos a tejo que nos encuentre dónde
está definida la macro _INCLUDE_POSIX_SOURCE
, puede que
hallemos por qué ocurre esto:
/usr/include$ find . -name "*.h" -exec grep "define .*_INCLUDE_POSIX_SOURCE" '{}' \; -print
# define _INCLUDE_POSIX_SOURCE
# define _INCLUDE_POSIX_SOURCE
# define _INCLUDE_POSIX_SOURCE
# define _INCLUDE_POSIX_SOURCE
# define _INCLUDE_POSIX_SOURCE
# define _INCLUDE_POSIX_SOURCE
./sys/stdsyms.h
# define _INCLUDE_POSIX_SOURCE
./utmp.h
Nos encuentra su definición en dos ficheros. Nos decantamos por el
primero, /usr/include/sys/stdsyms.h
. Antes de examinar su
contenido, podemos probar a ver si hay una página de manual del fichero
y, en efecto, la hay:
stdsyms(5) stdsyms(5)
NAME
stdsyms - description of HP-UX header file organization
DESCRIPTION
HP-UX header files are organized in a manner that allows for only a
subset of the symbols available in that header file to be visible to
an application that conforms to a specific standard. The ANSI-C,
[...]
En esta página se explica el porqué del asunto. El compilador de C que
viene por defecto en tejo (cc
) no es un compilador ANSI C.
Esto significa que, por ejemplo, no admite prototipos de funciones.
Como nos interesa trabajar con el estándar ANSI, usamos el compilador
c89
.
Las llamadas al sistema que usamos en nuestros programas se basan en
los estándares que vimos en clase: POSIX, AES, etc. El apaartado
ESTÁNDARES CUMPLIDOS
de la página de manual de
chown
dice:
ESTÁNDARES CUMPLIDOS
chown(): AES, SVID2, SVID3, XPG2, XPG3, XPG4, FIPS 151-2, POSIX.1
fchown(): AES, SVID3
Pues bien, cuando se usa el compilador de ANSI C, hay que especificarle
los estándares que queremos que cumpla. De todos, el estándar más general
de tejo es el HPUX. Para que funcione bien la compilación de las
prácticas, es necesario pedir ese estándar, definiendo la macro
_HPUX_SOURCE
al principio de nuestros programas. Esto se
puede hacer de tres maneras:
- Incluyendo al comienzo de todos los ficheros
fuente (
.c
) la línea #define
_HPUX_SOURCE
.
- Compilando todos nuestros programas con la opción del compilador
-D_HPUX_SOURCE
.
- Definiendo una variable de entorno en el fichero
.profile
que haga lo del punto anterior de un modo
automático: export CCOPTS="-D_HPUX_SOURCE".
© 2000 Guillermo González Talaván.