How do I find the 'temp' directory in Linux? I am writing a platform neutral C++ function that returns the temp directory. In Mac and Windows, there is an API that returns these results. In Linux, I'm stumped.
Check following variables:
The environment variable TMPDIR
The value of the P_tmpdir macro
If all fails try to use the directory /tmp.
You can also use tempnam function to generate a unique temporary file name.
Edit: Fair point from the commenter. tmpnam isn't a good choice these days; use mktemp/mkstemp instead.
Historical answer: Be POSIX compliant, and use tmpnam (which will give you a full filename in a temporary location).
Use the value of the $TMPDIR environment variable, and if that doesn't exist, use /tmp.
The accepted sequence, specifically from a GNU standpoint, is:
Check the environmental variable TMPDIR (getenv("TMPDIR")) only if
the program is not running as SUID/SGID (issetugid() == 0)
Otherwise use P_tmpdir if it is defined and is valid
and finally, should those fail, use _PATH_TMP available from paths.h
If you are adding an extension or module, check to see if the core provides a function for this purpose. For example, PHP exports php_get_temporary_directory() from main/php_open_temporary_file.h.
In standard c, you could try: P_tmpdir
Related
I want to make a small application that runs another application multiple times for different input parameters.
Is this already done?
Is it wrong to use system("myAp param"), for each call (of course with different param value)?
I am using kdevelop on Linux-Ubuntu.
From your comments, I understand that instead of:
system("path/to/just_testing p1 p2");
I shall use:
execl("path/to/just_testing", "path/to/just_testing", "p1", "p2", (char *) 0);
Is it true? You are saying that execl is safer than system and it is better to use?
In the non-professional field, using system() is perfectly acceptable, but be warned, people will always tell you that it's "wrong." It's not wrong, it's a way of solving your problem without getting too complicated. It's a bit sloppy, yes, but certainly is still a usable (if a bit less portable) option. The data returned by the system() call will be the return value of the application you're calling. Based on the limited information in your post, I assume that's all you're really wanting to know.
DIFFERENCES BETWEEN SYSTEM AND EXEC
system() will invoke the default command shell, which will execute the command passed as argument.
Your program will stop until the command is executed, then it'll continue.
The value you get back is not about the success of the command itself, but regards the correct opening of command shell.
A plus of system() is that it's part of the standard library.
With exec(), your process (the calling process) is replaced. Moreover you cannot invoke a script or an internal command. You could follow a commonly used technique: Differences between fork and exec
So they are quite different (for further details you could see: Difference between "system" and "exec" in Linux?).
A correct comparison is between POSIX spawn() and system(). spawn() is more complex but it allows to read the external command's return code.
SECURITY
system() (or popen()) can be a security risk since certain environment variables (like $IFS / $PATH) can be modified so that your program will execute external programs you never intended it to (i.e. a command is specified without a path name and the command processor path name resolution mechanism is accessible to an attacker).
Also the system() function can result in exploitable vulnerabilities:
when passing an unsanitized or improperly sanitized command string originating from a tainted source;
if a relative path to an executable is specified and control over the current working directory is accessible to an attacker;
if the specified executable program can be spoofed by an attacker.
For further details: ENV33-C. Do not call system()
Anyway... I like Somberdon's answer.
What is the difference between remove and unlink functions in C++?
Apart from the fact that unlink is unix-specific (as pointed out by Chris), we read in the POSIX manual:
If path does not name a directory, remove(path) is equivalent to unlink(path).
If path names a directory, remove(path) is equivalent to rmdir(path).
As for the directory-passed unlink, we read:
The path argument must not name a directory unless the process has appropriate privileges and the implementation supports using unlink() on directories. (...) Applications should use rmdir() to remove a directory.
remove is portable, and unlink is Unix-specific. :-P
The remove() function removes the file or directory specified by path.
If path specifies a directory, remove(path) is the equivalent of
rmdir(path). Otherwise, it is the equivalent of unlink(path).
From: man remove.
Good Luck ;)
unlink is not unix-specific, i don't know why people're saying that. see io.h. although you'll probably have to do something like
#define unlink _unlink
http://msdn.microsoft.com/en-us/library/1c3tczd6%28v=VS.100%29.aspx
http://msdn.microsoft.com/en-us/library/2da4hk1d%28v=VS.100%29.aspx
remove() is part of the C++ standard (N4860 29.11.14.30). unlink() is not.
This shell script
#!/bin/csh
set VAR=12345
echo $VAR
will peacefully give the output 12345 at shell.
I need to use C++ to do the same in some part of the code:
string str = "12345";
retValue="set var1= "+str;
system(retValue1.c_str());
system("echo $var1");
This doesn't create a system variable var1 and echos null which is understandable as each system function would create a child process with different environment variables. So I combine them as follows using just one system function...but it echos null again.
retValue="set var1= "+str;
retValue1=retValue+";\n echo $var1";
system(retValue1.c_str());
Can someone please guide me to set up the system variable thru C++.
Thanks a lot in advance!
Look at setenv in <cstdlib>:
#include <cstdlib>
setenv("VAR", "12345", true);
You basically can't do that.
You could call putenv to change environment variables in your own process and in all future children processes, but there is no way (and this is good) to change the environment of the parent shell process.
You could have a use convention for your C++ program that e.g. it is outputting some shell commands to be sourced (or eval-ed) by the user. An example of this is ssh-agent -s.
You can use putenv().
#include <cstdlib>
...
putenv("VAR=12345");
This is very convenient, but the string is not copied by putenv. This means that if you modify it later, then you modify the environment. That's not an issue for a literal, but the way you are forming your strings, using std::string is not readily compatible with putenv().
The alternative then is to use setenv()
#include <cstdlib>
...
setenv("VAR", "12345", true);
With setenv(), copies of the input are made and you are safe to dispose of the strings after calling setenv().
The function you want is probably putenv(). You didn't specify which OS you are on, so I'll assume Linux because that's the man page I have handy:
int putenv(char *string);
The putenv() function adds or changes the value of environment
variables. The argument string is of the form name=value. If name
does not already exist in the environment, then string is added to the
environment. If name does exist, then the value of name in the
environment is changed to value. The string pointed to by string
becomes part of the environment, so altering the string changes the
environment.
IIRC, there is a putenv on win32 as well. Finally you might try looking at this question, possibly a dup
Above answers explains correctly as to how to set environment variable from a C++ program which is basically setenv()
The only other point i wanted to make is that why your approach doesn't work? The reason is, that when a process is loaded, the system command is loaded with new context - an equivalent of a new shell. Actually your environment variable is getting set but when you comeback it is lost.
Refer to this http://pubs.opengroup.org/onlinepubs/007904975/functions/setenv.html.
Infact, the setenv() sets the env variables of parent process! Which is why it works for you.
Note that the otherwise excellent CPPreference site does not seem to mention setenv among the functions available in the <cstdlib> header, only getenv. This may not be a problem though as I could use setenv by #include-ing <cstdlib> on a Centos 7 system with GCC 9.1. I suspect in most cases <cstdlib> is just a thin wrapper around <stdlib.h>.
Another small thing to note is that setenv takes C-style character arguments (also for the value of the environment variable to be set). If you use C++ strings (as you should), don't forget to convert them using their .c_str() method.
Is there a cross-platform function in Qt that is equivalent to the MoveFile function in Windows and the mv command in Linux?
Sure, QDir::rename() following the old Unix / POSIX tradition of calling this rename.
Which makes sense if you think of a file with its complete path: the underlying inodes just get assigned a different path/file label.
You would use QDir::rename() but be beware of the special cases when rename() can fail:
On most file systems, rename() fails
only if oldName does not exist, if
newName and oldName are not on the
same partition or if a file with the
new name already exists. However,
there are also other reasons why
rename() can fail. For example, on at
least one file system rename() fails
if newName points to an open file.
QUrlOperator::copy() is an alternative to QDir::rename() that may also work for you.
In C++, on Linux, how can I write a function to return a temporary filename that I can then open for writing?
The filename should be as unique as possible, so that another process using the same function won't get the same name.
Use one of the standard library "mktemp" functions: mktemp/mkstemp/mkstemps/mkdtemp.
Edit: plain mktemp can be insecure - mkstemp is preferred.
tmpnam(), or anything that gives you a name is going to be vulnerable to race conditions. Use something designed for this purpose that returns a handle, such as tmpfile():
#include <stdio.h>
FILE *tmpfile(void);
The GNU libc manual discusses the various options available and their caveats:
http://www.gnu.org/s/libc/manual/html_node/Temporary-Files.html
Long story short, only mkstemp() or tmpfile() should be used, as others have mentioned.
man tmpfile
The tmpfile() function opens a unique temporary file in binary
read/write (w+b) mode. The file will be automatically deleted when it
is closed or the program terminates.ote
mktemp should work or else get one of the plenty of available libraries to generate a UUID.
The tmpnam() function in the C standard library is designed to solve just this problem. There's also tmpfile(), which returns an open file handle (and automatically deletes it when you close it).
You should simply check if the file you're trying to write to already exists.
This is a locking problem.
Files also have owners so if you're doing it right the wrong process will not be able to write to it.