From answers and comments on this question, I understand that getenv is defined by the C++ standard, but setenv is not. And indeed, the following program
#include <cstdlib>
#include <iostream>
int main ( int argc, char **argv )
{
std::cout << std::getenv("PATH") << std::endl; // no errors
std::setenv("PATH", "/home/phydeaux/.local/bin:...", true); // error
}
does not compile for me (clang 3.9).
Why was one of these seemingly complementary functions standardised but not the other?
The C90 standard includes getenv(); therefore, the C++98 standard did too.
When the C standard was originally created, the precedent for environment setting was putenv(); the setenv() function was not devised until later. The standard committee avoided creating new functions when it could, but also avoided standardizing problematic functions when possible (yes, localeconv() and gets() are counter-examples). The behaviour of putenv() is problematic. You have to pass it memory which is not of automatic duration, but you can't know whether you can ever use it again. It's like a forced memory leak. It was A Good Thing™ that putenv() was not standardized.
The rationale for the C standard explicitly says (§7.20.4.5, p163):
A corresponding putenv function was omitted from the Standard, since its utility outside a multi-process environment is questionable, and since its definition is properly the domain of an operating system standard.
Platform-specific APIs step in and provide the missing functionality in a way suitable to them.
The first editions of the POSIX standard (1988 trial use; 1990) did not include setenv() or putenv(). The X/Open Portability Guide (XPG) Issue 1 did include putenv() based on its appearance in the SVID (System V Interface Definition) — which did not include setenv(). The XPG Issue 6 added setenv() and unsetenv() (see the history sections for the functions at the URLs linked to). Curiously, on a Mac running macOS Sierra 10.12.6, man 3 setenv has a history section that identifies:
The functions setenv() and unsetenv() appeared in Version 7 AT&T UNIX. The putenv() function appeared in 4.3BSD-Reno.
This is unexpected and probably erroneous since the UNIX Programmer's Manual Vol 1 (1979) does not include any of putenv(), setenv() or unsetenv(). The putenv() function was added to the AT&T variants of Unix at some stage in the 80s; it was in the SVID and documented by the time SVR4 was released in 1990 and may have been part of System III. I think they almost have the platforms reversed. 4.3BSD-Reno was released in June 1990, after both the first C and POSIX standards were released.
There was some discussion in comments with Random832 , now removed, mentioning TUHS – The Unix Heritage Society as a source of information about ancient versions of Unix. The chain included my observation: If nothing else, this discussion emphasizes why the standards committees did well to steer clear of 'setting the environment'! It appears that putenv() was not in 7th Edition UNIX, contrary to my memory. I'm fairly sure it was available in a system I used from 1983, which was a lot of 7th Edition with some material from System III, some from PWB. It is a part of SVR4 (I've a manual for that), and was defined in some version of the SVID (probably before SVR4).
The C rationale also mentions concerns about gets() but included it despite those concerns; it was (very sensibly) removed from C11, of course (but POSIX still refers to C99, not C11).
setenv is not possible in some of the original environments C was defined for.
getenv allows you to see your environment. creating a new process with exec[lv][p][e] allows you to create a child with an inherited or new environment.
However, setenv, would modify the state of the calling process, which wasn't always possible.
I guess it is because it increases the writable interface for the caller, and was not needed originally, and is a security risk these days.
Related
I've been using #include <minmax.h> in my scripts and using min() and max() as expected. I showed this to someone and they had never seen it before, said it wasn't working for them and asked me why I wasn't including <algorithm> and calling std::min() or std::max().
So my question is basically, why aren't I? I found this in a book on C++: "C++ Design Patterns and Derivatives Pricing". Googling "minmax.h", I find a reference to that very book in the top result, so that even more so makes me think it's something abnormal.
Is anyone able to tell me what this is?
The C++ programming language is accompanied by the C++ Standard Library. There is no <minmax.h> header in the C++ Standard Library. No header in the standard-library has the .h extension. Furthermore, the header is not part of the ported C standard library either, as those headers have the c prefix, like <cmath> (which replaces the C standard-library <math.h> header), <ctime>(which replaces the <time.h> header) when used from the C++ Standard Library.
The std::min and std::max functions are declared inside the <algorithm> header.
That being said, there indeed appears to be some MS header called <minmax.h> inside the C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt folder which defines min and max macros, not functions. But, that is some implementation specific header, and you should be using the standard <algorithm> header instead.
why aren't I?
People do all sort of odd things that they heard about somewhere once, be it in school or that came up as some "solution" that fixed their immediate need (usually under timeline pressure). They then keep doing things the same way because they "work". But I'm glad you stopped for a minute to ask. Hopefully we'll steer you back onto the portable C++ route :)
No, there's no need to use the non-standard minmax.h header. On Windows you need to define the NOMINMAX macro before you include any headers whatsoever, and include <algorithm> right after this macro definition. This is just to free the min and max symbols from being taken over by ill-conceived WINAPI macros. In C++, std::min etc. are in the <algorithm> header and that's what you ought to be using. Thus, the following is portable:
#define NOMINMAX
#include <algorithm>
// other includes
#undef NOMINMAX
// your code here
See this answer for details for Windows.
An ancient reference w.r.t. C++, using ancient compilers, supplying examples using non-standard C++ (e.g. headers such as minmax.h)
Note that the book you are mentioning, C++ Design Patterns and Derivatives Pricing (M.S. Joshi), was first released in 2004, with a subsequent second edition released in 2008. As can be seen in the extract below, the examples in the book relied on successful compilation on ancient compiler versions (not so ancient back in 2004, but still far from recent versions).
Appendix D of the book even specifically mentions that the code examples covered by the book may not be standard-compliant, followed by the pragmatic advice that "[...] fixing the problems should not be hard" [emphasis mine]:
The code has been tested under three compilers: MingW 2.95, Borland 5.5, and Visual C++ 6.0. The first two of these are available for free so you should have no trouble finding a compiler that the code works for. In addition, MingW is the Windows port of the GNU compiler, gcc, so the code should work with that compiler too. Visual C++ is not free but is popular in the City and the introductory version is not very expensive. In addition, I have strived to use only ANSI/ISO code so the code should work under any compiler. In any case, it does not use any cutting-edge language features so if it is not compatible with your compiler, fixing the problems should not be hard.
The compiler releases listed above are very old:
Borland 5.5 was released in 2000,
Visual C++ 6.0 was released in 1998,
GCC 2.95 was released in 1999.
Much like any other ancient compiler it is not surprising that these compilers supplied non-standard headers such as minmax.h, particularly as it seems to have been a somewhat common non-standard convention, based on e.g. the following references.
Gnulib Module List - Extra functions based on ANSI C 89: minmax.h, possibly accessible in GCC 2.95,
Known problems in using the Microsoft Visual C++ compiler, version 6.0:
The MS library does not define the min and max algorithms, which should be found in The workaround we use is to define a new header file, say minmax.h, which we include in any file that uses these functions: [...]
What is the worst real-world macros/pre-processor abuse you've ever come across?:
Real-world? MSVC has macros in minmax.h, called max and min, which cause a compiler error every time I intend to use the standard std::numeric_limits::max() function.
Alternative references for the C++ language
Based on the passage above, the book should most likely be considered primarily a reference for its main domain, quant finance, and not such much for C++, other than the latter being a tool used to cover the former.
For references that are focusing on the C++ language and not its application in a particular applied domain (with emphasis on the latter), consider having a look at:
StackOverfow C++ FAQ: The Definitive C++ Book Guide and List.
In the C++17 filesystem library, we got std::filesystem::remove(path), which — as I understand it — is a direct port of boost::filesystem::remove(path) from Boost.Filesystem.
But C++ inherited from C89 a very similar function called std::remove(path), which is also documented as a way to remove a file from the filesystem. I'm vaguely aware of some pitfalls with this function, e.g. I believe I have heard that on Windows std::remove cannot be used to remove a file that is still being held open by the current process.
Does std::filesystem::remove fix these issues with std::remove? Should I prefer std::filesystem::remove over std::remove? Or is the former just a namespaced synonym for the latter, with the same warts and pitfalls?
The title of my question asks for the difference between boost::filesystem::remove(path) and std::remove(path) because I figure that std::filesystem::remove(path) may not have been implemented by a lot of library vendors yet, but my understanding is that it's supposed to be basically a direct copy of the Boost version. So if you know about Boost.Filesystem on Windows, you probably know enough to answer this question too.
Checking the standard library sources installed with my MSVC, std::experimental::filesystem::remove calls its internal _Unlink helper, which simply calls _wremove, which simply calls Windows DeleteFileW. Similarly, boost::filesystem::remove also just calls DeleteFileW on Windows.
std::filesystem::remove is specified by reference to POSIX remove, but the global wording in [fs.conform.9945] makes clear that implementations are not required to provide the exact POSIX behavior:
Implementations should provide such behavior as it is defined by
POSIX. Implementations shall document any behavior that differs from
the behavior defined by POSIX. Implementations that do not support
exact POSIX behavior should provide behavior as close to POSIX
behavior as is reasonable given the limitations of actual operating
systems and file systems. If an implementation cannot provide any reasonable behavior, the implementation shall report an error as specified in [fs.err.report]. [ Note: [...] ]
Implementations are not required to provide behavior that is not supported by a particular file system. [ Example: [...] ]
Any quirks in ::remove (that is about the actual act of removing rather than identification of the file to be removed) are likely due to limitations of the underlying OS API. I see no reason to think that an implementation of std::filesystem::remove on the same operating system will magically do better.
I've been searching for a getpass() alternative and it's in fact the simplest way to hide a password input I've founded. It's kind of a loss for C++ here, being such easy function with a lot of use.
What i would like to know is why is it considered obsolete, does it have any security issues ?
And can/should i still use it professionally, disregarding the warnings and taking them as "exaggerated" ?
Why is getpass() considered an obsolete function?
According to this man page
The getpass() function is not threadsafe because it manipulates
global signal state.
The getpass() function is scheduled to be withdrawn from a future version
of the X/Open CAE Specification.
can/should i still use it professionally
If your C library has the function, then you can use it.
If you consider any of: the lack of thread safety, or the manipulation of global signal state in general, or the fact that as an obsolete function it may be removed in a future version of the C library that conforms to a future POSIX version, a problem, then you should not use it.
The recommended alternative is to write your own function, using termios and disable the ECHO flag. Complete minimal substitute in glibc manual.
The term "obsolete" appears to be an add-on from implementers; the actual SUSv2 was less direct:
The return value points to static data whose content may be overwritten by each call.
This function was marked LEGACY since it provides no functionality which a user could not easily implement, and its name is misleading.
The "obsolete" is mentioned in mailing list in 2003 Re: getpass obsolete?, which pointed to an OSF1/Tru63 manual page citing the lack of thread-safe capability, but in regard to the standard at that point in time was only supported by the comments in SUSv2.
I am trying to implement the code given in this page
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366062%28v=vs.85%29.aspx
I am using mingw (gcc) to compile this.
But the following lines cannot be compiled. I have included 'time.h'. I searched but cannot locate this '_localtime31_s' or its equivalent in gcc.
error = _localtime32_s(&newtime, (__time32_t*) &pAdapter->LeaseObtained);
error = asctime_s(buffer, 32, &newtime);
Where is the time functions here?
Thanks
The functions localtime_s and asctime_s are Microsoft-specific extensions, provided by (certain versions of) the MS runtime library. This is provided by the MS header files. Since those are copyright MS and not allowed for free distribution, mingw provides its own versions of headers - and these probably don't contain these extensions (they certainly didn't a while back when I was using mingw on my local machine - my main machine these days runs Linux...).
Note that casting the time value to time32_t * is probably a bad idea - it is almost certainly going to bite you if you ever compile your code with a time_t that isn't a 32-bit value.
The localtime_r function is a semi-standard version that could be used instead of localtime_s (you will need to pay attention to 32 vs 64-bit time values). You can certainly also use localtime (aside from having to turn off MS's annoying "this function is not safe, please use ..._s instead" - I don't REALLY want to convert my 100 uses of strcpy to strcpy_s that work perfectly fine because it has already been checked elsewhere).
Similarly there is asctime_r which provides a re-entrant version.
You could, perhaps, also add the prototypes for these functions to your file somewhere, I believe that would, as long as you are compiling for Windows, solve the problem:
Link to MS function documentation: localtime_s and asctime_s.
MinGW-w64 provides an option to enable the secure CRT functions. Note there are compatibility issues with Windows XP, where msvcrt.dll does not contain these functions and your application will not work in that environment.
These are standardized in C11 Annex K, which is optional and may be missing on C11 conformant systems.
This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Closed 1 year ago.
Based on the most recent draft of C++11, C++ refers to ISO/IEC 9899:1999/Cor.3:2007(E) for the definitions of the C library functions (per §1.2[intro.refs]/1).
Based on the most recent draft of C99 TC3, The gets function is obsolescent, and is deprecated. (per §7.26.9/2)
Can I safely say that gets() is deprecated in both C and C++?
Deprecated means you shouldn't use it and it might be removed in the future. Since both standards say it is deprecated, that means it is deprecated, officially.
Does it matter? The only way you can ever use gets is if stdin is known to be attached to a file whose contents you have full control over. This condition is almost impossible to satisfy, especially on multiprocess systems where other processes may modify files asynchronously with respect to your program. Therefore, for all practical purposes, any program using gets has undefined behavior (i.e. there are possible inputs/environmental conditions for which it will have undefined behavior), and in particular UB which is likely to lead to privilege compromise if your program has higher privileges than the provider of the data.
Edit: OK, here's one safe use of gets, about the only one I can think of right off...
if (feof(stdin)) gets(buf);
Of course some buggy implementations (possibly including glibc..?) permit reads even when the EOF indicator is already set for a stream, so....
Even code which would be broken by the removal of gets() from the library would, after such removal, be less broken than it was before such removal. I suppose it might be necessary for compiler vendors to include it in a "fully-standard compliant" mode, but the number of circumstances where it could safely be used is so vanishingly small that it would probably be reasonable to exclude it from a "normal" build.
It's going to be a while until C++11 is implemented everywhere.
Also, most compilers doesn't even fully support C99 yet.
Microsoft's, for instance, does not.
So no, it's not deprecated in both C and C++.
Well it was removed altogether from the C11 standard, so I'd take that as a yes.