Is the crypt() function declared in unistd.h or crypt.h?
Asked Answered
A

2

5

I'm using GCC 4.6.0 (on an otherwise unidentified platform).

I am using the crypt() function to encrypt a password.

I have never used that function before so I checked out the main page:

man 3 crypt

And it says to include the unistd.h header.

However, when I did that, I got an implicit warning for the crypt function.

warning: implicit declaration of function ‘crypt’ [-Wimplicit-function-declaration]

I did a bit of searching and I found that you have to include the crypt.h. However, how come it doesn't say that in the man page?

Aube answered 25/5, 2011 at 16:43 Comment(8)
Please post the exact warning you are getting at compile time.Christiansen
@Michael, I have appended my question with the warning I am getting.Aube
You do compile with -lcrypt ?Bren
possible duplicate of C : crypt functionChristiansen
@Henno, yes I am compiling with lcrypt libcrypt.so.1 => /lib64/libcrypt.so.1. From ldd executable.Aube
@Micheal, I did search before posting. That is how I found out to include the crypt.h. However, it didn't explain that the man pages say you should include unistd.h?Aube
Not a duplicate - it's the difference between #include <math.h> and -lm, for an analogy.Stuffy
Please specify the platform you are compiling on, and also specify the command line options to the compiler that you're using. Is -std=c99 one of the options, for example?Ponderous
C
3

It also says #define _XOPEN_SOURCE (before including unistd.h) in my man page. So you should probably add it to expose the declaration of crypt.

EDIT

I just tried it. Including unistd.h and #define _XOPEN_SOURCE before it does the trick. Including it alone isn't enough.

Using

gcc version 4.6.0 20110429
GNU C Library stable release version 2.13

Looking into unistd.h:

/* XPG4.2 specifies that prototypes for the encryption functions must
   be defined here.  */
#ifdef  __USE_XOPEN
/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
extern char *crypt (__const char *__key, __const char *__salt)
     __THROW __nonnull ((1, 2));
Coupon answered 25/5, 2011 at 16:45 Comment(8)
I did add the _XOPEN_SOURCE. However, I was still getting the warning with it.Aube
You don't just define it but give it a value. The value should be 700 for the latest standard.Cannice
@R.. That sounds sensible, but the man page says #define _XOPEN_SOURCE. I haven't tried it though.Coupon
The man pages are a joke. Read the standard.Cannice
@R.. The man-pages are also [often] more system-specific than the standard... take as you will.Carnap
@R, I did the following: #define _XOPEN_SOURCE 700. However, still getting the same error. Why not just use the crypt.h header that solves this problem?Aube
@ant2009: The line #define _XOPEN_SOURCE 700 needs to be before ALL of your include files—if you put it in after some other include file, even if it's before <unistd.h>, it won't work.Pepys
@Adam, you are correct. I only added before the <unistd.h> header file. Now that I have placed it on the first line. It compiles ok.Aube
P
3

The POSIX standard for crypt() says that it should be declared in <unistd.h>, so that's what you need to include.

However, depending on what other compiler options you specify, you may or may not see it.

I currently use a header I call "posixver.h" which contains the code:

#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2001 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600   /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */

On the systems where I work, setting _XOPEN_SOURCE to 700 would be an exercise in frustration and futility, however much I'd like to be able to do so. But these options normally make my code work correctly on Linux, HP-UX, MacOS X, AIX and Solaris - the Unix-like platforms I normally work on.

And this works when I set GCC into -std=c99 mode. If you use -std=gnu99, you probably don't need the header at all; it automatically enables C99 standard plus extensions.

Incidentally, I used to have this stanza at the top of individual source files. As the number of files containing the stanza grew (encroaching on hundreds of files), I realized that when I needed to adjust the settings, I had a monstrous editing job ahead of me. Now I have the one header and I'm retrofitting it into the files that have the stanza so I change one file (the header) to effect a change for all my code - once I've finished undoing the damage I did.

Ponderous answered 26/5, 2011 at 5:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.