While executing the following code:
#include <iostream>
using std::cout;
#include <cstdio>
/* stdin
stdout
FILE
freopen */
int main() {
for (FILE* f : {stdin, stdout})
if (nullptr == freopen(nullptr, (f == stdin) ? "rb" : "wb", f))
cout << f << '\n';
}
... I get the following output:
0x7edde180
... which means that freopen(nullptr, "rb", stdin) returned nullptr, failing.
Am I doing anything wrong?
Compiler: i586-mingw32msvc-g++ on the GNU OS
Environment: wine (x86)
http://msdn.microsoft.com/en-us/library/wk2h68td.aspx
If path, mode, or stream is a null pointer, or if filename is an empty string, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return NULL.
In short, it looks like the MSVC++ implementation of freopen does not allow for a NULL pathname.
Related
My code(below) fails:
11:Resource temporarily unavailable
The code is running as root (in an abrt hook) but has seteuid to the user that the pid in question is running as.
Writing to /proc/self/coredump_filter from within the process works OK.
How can I write to the coredump_filter from the abrt hook?
void SetDumpFlags(pid_t pid, int dumpflags){
std::string c_filter_name = "/proc/" + std::to_string( pid ) + "/coredump_filter";
int f = open( c_filter_name.c_str(), O_WRONLY );
if (f < 0) {
fprintf( log, "Couldn't open %s\n", c_filter_name.c_str());
bail_out(1);
}
int wsz = write( f, &dumpflags, sizeof dumpflags);
if (wsz != sizeof dumpflags){
fprintf( log, "Couldn't write to %s, %d:%s\n", c_filter_name.c_str(),errno, strerror(errno));
close( f );
bail_out(1);
}
close( f );
fprintf( log, "Pid %d, dump filter set to 0x%x\n", pid, dumpflags);
}
I tried to replicate your problem with a C example
(I would use C++11 but I'm on an ancient netbook without C++11 and it'd be hard to get it here and aclimate in the language).
I got an EACCESS on the open (and my guess you might be getting it too but the errno could get overwritten elsewhere?).
It seems the coredump_filter (at least on this Linux 3.2) starts as owned by
root and the seteuid doesn't change it.
I tried chown before setuid to no avail.
What did work (as expected) was to open the fd while you're still root
and keep it open during the seteuid call.
Then I could write to the file again successfully even after my euid changed.
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define FLAGS "0x11"
#define FLAGSSZ (sizeof(FLAGS)-1)
int main()
{
pid_t pid = getpid();
char buf[sizeof("/proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(buf,"/proc/%ld/coredump_filter",(long)pid);
int f;
if(0>(f=open(buf,O_WRONLY|O_TRUNC))) {perror("open");exit(1);}
if(FLAGSSZ != write(f,FLAGS,FLAGSSZ)){perror("write");exit(1);}
puts("ok");
char cat[sizeof("cat /proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(cat,"cat /proc/%ld/coredump_filter", (long)pid);
system(cat);
char ls[sizeof("ls -l /proc/XXXXXXXXXXXXXX/coredump_filter")];
sprintf(ls,"ls -l /proc/%ld/coredump_filter", (long)pid);
system(ls); //owned by root, not writable by others
if(0>chown(buf,getuid(),getgid())){perror("chown"); exit(1); }
//chown returns success but ls -l doesn't agree
system(ls); //still owned by root
if(0>seteuid(getuid())){
perror("seteuid");
exit(1);
}
//can't reopen because of the perms but can still
//use the old fd if we kept it open
if(0>lseek(f,SEEK_SET,0)){perror("lseek"); exit(1);}
#define ALTFLAGS "0x22"
#define ALTFLAGSSZ (sizeof(ALTFLAGS)-1)
if(ALTFLAGSSZ != write(f,ALTFLAGS,ALTFLAGSSZ)){perror("write");exit(1);}
puts("ok");
system(cat);
}
I compiled with gcc c.c and made the a.out setuid root with sudo sh -c 'chown 0 $1 && chmod u+s $1' - a.out before running it.
I was trying to write data to the coredump_filter whereas I should have written a string! Doing it with a literal (e.g. #define FLAGS "0x11" as in the answer given by PSkocik ) fixes the problem.
The /proc/nnnnn/coredump_filter file is owned by the user that process nnnnn is running as. In my case this is root for some processes and another user for others. Switching user (in the abrt hook) to the appropriate user, before trying to write the coredump_filter, works OK.
I've recently switched a project from using the VS2013 compiler to VS2017, and now the following code appears not to be working:
#include <windows.h>
#include <Fcntl.h>
#include <io.h>
#include <iostream>
#include <exception>
if( RedirectOutput )
{
//Setup stdout
HANDLE handle_stdout = GetStdHandle( STD_OUTPUT_HANDLE );
int fileDesc_stdout = _open_osfhandle( (long)handle_stdout, _O_TEXT );
if( fileDesc_stdout == -1 )
{
throw std::exception( "fileDesc_stdout is not valid" );
}
FILE* new_stdout = _fdopen( fileDesc_stdout, "w" );
if( !new_stdout )
{
throw std::exception( "new_stdout is not valid" );
}
FILE old_stdout = *stdout;
*stdout = *new_stdout;
std::cout.clear();
std::cout << "Output Redirected!\n";
}
This code is intended to redirect standard output to a console window, either the one that kicked off the current process or a console that is created via AllocConsole. (I've added the last line for testing purposes.)
The first time writing to cout occurs, the following exception is thrown (it otherwise doesn't write output and fails silently from then on):
Debug Assertion Failed!
Program: w:\build\MyApp.exe
File: minkernel\crts\ucrt\src\appcrt\stdio_flsbuf.cpp
Line: 26
Expression: ("inconsistent IOB fields", stream->_ptr - stream->_base >= 0)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
I can see that stdout is coming from corecrt_wstdio.h, but when I insert a breakpoint and add a watch, it says that the stdout is undefined, so I can't check the value.
Any ideas?
So I searched around a bit and found this post on SO.
Essentially, all of the code I posted can be replaced with the following:
freopen("CONOUT$", "w", stdout);
The first parameter of freopen is a filename, so I wonder if CONOUT$/CONIN$ represent an actual file, or if the function treats that input as a special case.
I am trying to print the path of the current directory using
this
execl ("/bin/pwd", "pwd", NULL);
output: /home/user/Ubuntu
and want to print a desired text before the current path.
for example:
my name /home/user/ubntu
how this will be done?
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
using namespace std;
int main(){
string command;
while(command != "exit"){
cout<< "B-17235"<<return execl ("/bin/pwd", "pwd", NULL);
cin>> command;
}
return 0;
}
Think that the majority of Unix-Linux-Gnu commands are written in C or C++. Generally there are direct API calls either system calls (man 2) or standard C library (man 3) to get the information or do the job.
To get working directory, just use getcwd() as suggested by alk.
char buffer[256];
if (NULL == getcwd(buffer, sizeof(buffer))) {
perror("can't get current dir");
return 1;
}
If you wanted to get the output of a more complex command, the most direct way would be to use popen that encloses the fork, exec, and pipe management for you :
FILE *fd = popen("/bin/pwd", "r");
char buffer[256];
if (fgets(buffer, sizeof(buffer), fd) == NULL) {
perror("can't read command");
return 1;
}
if (buffer[strlen(buffer) - 1] != '\n') {
fprintf(stderr, "path too long";
return 1;
}
pclose(fd);
// ok the working directory is is buffer
You should not use that for a command as simple as pwd.
And don't forget : man is your friend ! man getcwd and man popen will give you plenty of information ...
I am trying to print the path of the current directory
Use the library function getcwd().
To have the function available it might be necessary to #define _XOPEN_SOURCE 500 or similar (please see the man-page linked above for details on this).
I am using following code for extracting output of system command .
I have not set path for "pic" in PATH variable. and i want to store
output of command "which pic" and do not want to display it on console.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main ()
{
FILE *fp;
int status;
char path[1035];
char *command = "which pic";
/* Open the command for reading. */
fp = popen(command, "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(0);
}
/* Read the output a line at a time - output it. */
while (fgets(path, sizeof(path)-1, fp) != NULL) {
cout<<"<<<<<<<<<<,"<<endl;
printf("%s", path);
}
/* close */
pclose(fp);
return 0;
}
but it displaying following output in console :
which: no pic in(/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin)
Run "which pic 2>&1" as your command. You want to capture all output from which, including its errors (which are sent to stderr).
Is it possible to redirect assert output to a file when its parameter is false? I know its default behavior is to write a message to stderr, but the following didn't work as I expected:
#include <iostream>
#include <assert>
#include <fstream>
using namespace std;
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
ofstream ofs;
ofs.open("test.txt", ios_base::out);
ofs << "A";
cerr << "B";
cerr.rdbuf(ofs.rdbuf());
cerr << "C";
assert(1 == 2);
return 0;
}
//---------------------------------------------------------------------------
Results in test.txt:
AC
And results in stdout:
B
Assertion failed: 1 == 2, file C:\xxx\Unit1.cpp, line 14
Abnormal program termination
I was expecting that these 2 last lines printed in stdout were in test.txt file though.
I've also tried using, instead of...
cerr.rdbuf(ofs.rdbuf());
the following:
freopen("test.txt", "a", stderr);
but it hasn't worked as well.
I've also seen some posts (as C: how to redirect stderr from System-command to stdout or file?) suggesting dup2 to redirect streams such as stderr, which that is defined in unistd.h. But I'm at Windows using C++Builder and it doesn't seem available.
You can redirect all output to stderr, or any other standard file handle to a file at the start of your program.
freopen( "error.log","w",stderr);
Read about this here:
http://support.microsoft.com/kb/58667
#edit: if the output goes to stdout, then you need to do:
freopen( "error.log","w",stdout );
If you want to append and not overwrite the error.log:
freopen( "error.log","aw",stdout );