I tried to compiler the following code(minimum example, see the edit for the whole code):
// a.c
#include <stdio.h>
#define _XOPEN_SOURCE
#include <unistd.h>
int main(int argc, char* argv[])
{
puts((const char*) crypt("AAAA", "$6$2222"));
return 0;
}
Using clang-7 -lcrypt a.c
and it emitted the following warning:
minimum.c:8:24: warning: implicit declaration of function 'crypt' is invalid in C99 [-Wimplicit-function-declaration]
puts((const char*) crypt("AAAA", "$6$2222"));
^
minimum.c:8:10: warning: cast to 'const char *' from smaller integer type 'int' [-Wint-to-pointer-cast]
puts((const char*) crypt("AAAA", "$6$2222"));
^
2 warnings generated.
But ./a.out
did seem to work:
$6$2222$6GKY4KPtBqD9jAhwxIZGDqEShaBaw.pkyJxjvSlKmtygDXKQ2Q62CPY98MPIZbz2h6iMCgLTVEYplzp.naYLz1
I found out that if I remove #include <stdio.h>
and puts
like this:
// new_a.c
#define _XOPEN_SOURCE
#include <unistd.h>
int main(int argc, char* argv[])
{
crypt("AAAA", "$6$2222");
return 0;
}
Then there is no warnings.
How to fix these warnings without removing #include <stdio.h>
?
Edit:
Whole program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _X_OPEN_SOURCE
#include <unistd.h>
#include <assert.h>
void* Calloc(size_t cnt, size_t size)
{
void *ret = calloc(cnt, size);
assert(ret);
return ret;
}
size_t GetSaltLen(const char *salt)
{
size_t salt_len = strlen(salt);
assert(salt_len > 0);
assert(salt_len <= 16);
return salt_len;
}
char* GetSaltAndVersion(const char version, const char *salt)
{
size_t saltlen = GetSaltLen(salt);
/*
* The format of salt:
* $one_digit_number$up_to_16_character\0
* For more info, check man crypt.
*/
char *ret = (char*) Calloc(1 + 1 + 1 + saltlen + 1, sizeof(char));
char *beg = ret;
*beg++ = '$';
*beg++ = version;
*beg++ = '$';
memcpy((void*) beg, (const void*) salt, saltlen + 1);
return ret;
}
void crypt_and_print(const char *passwd, const char *salt_and_version)
{
char *result = crypt(passwd, salt_and_version);
assert(puts(result) != EOF);
}
int main(int argc, char* argv[])
{
if (argc != 4) {
fprintf(stderr, "argc = %d\n", argc);
return 1;
}
char *salt_and_version = GetSaltAndVersion(argv[2][0], argv[3]);
crypt_and_print(argv[1], salt_and_version);
free(salt_and_version);
return 0;
}
I have tried as @Andrey Akhmetov suggested and put the #define
onto the first line, but the warnings did not disappear.
The macro _XOPEN_SOURCE
is documented in feature_test_macros(7)
. In particular, the manpage states:
NOTE: In order to be effective, a feature test macro must be defined before including any header files. This can be done either in the compilation command (
cc -DMACRO=value
) or by defining the macro within the source code before including any headers.
When you include stdio.h
, you indirectly include features.h
, which uses the feature test macros as defined at that point. In particular, since _XOPEN_SOURCE
and friends aren't defined at that point, crypt.h
does not declare crypt
.
By the time you define _XOPEN_SOURCE
it is too late, since features.h
has an include guard preventing it from being included twice.
By swapping the order of the first two lines, the code works without raising this warning on my system:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
puts((const char*) crypt("AAAA", "$6$2222"));
return 0;
}
Your larger example does not work for a second reason: You wrote _X_OPEN_SOURCE
as the name of the macro, while the correct name is _XOPEN_SOURCE
.