I'm having some trouble while trying to open a local file in google-chrome as it gives me a weird URL in google chrome but prints just fine in the console.
Here is my code:
int subId = 902 ;
system(("google-chrome "+localURL+"initialFr.html?id="+to_string(subId)).data());
std::cout << ("google-chrome "+localURL+"initialFr.html?id="+to_string(subId)).data() << std::endl
Here is the output I get in the console:
file:///home/lonni/Questionnaire/initialFr.html?id=902
Here is the address I get in chrome:
file:///home/lonni/Questionnaire/initialFr.html%3Fid=902
I am using c++11 (hence the .data()) on ubuntu.
Would you guys know where this comes from?
Thanks in advance
The file: URL schema does not support HTTP schema parameter passing. Those parameters are intended to be interpreted by an HTTP server.
If you need to pass a parameter, you can use an anchor, for example:
file:///home/lonni/Questionnaire/initialFr.html#902
My application is an server application that accepts some predefined commands from user and displays respective output that is taken from XML files present at the server end.
For parsing XML file I am using xerces-c library version 3.1.2 from apache. The application works fine when ran manually on a terminal.
But I wanted to run the application through telnet on a network so that I can give inputs to the application via telnet and receive output on a remote system too. For this I used inetd super server and added below line in inetd.conf:
vterm stream tcp nowait root /path/to/my/binary/vterm vterm
Then added below line in /etc/services to make it listen on port 5000
vterm 5000/tcp
After that when I tried to connect to my application I used to get below message:
msatyam#sabayon ~/programming/cpp/xml $ telnet localhost 5000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
When the above connection closed message came I thought I have not configured properly my application with inetd. So, I replaced my binary with a simple binary which didn't used any extra libraries. Just simple cin's and cout's, which worked perfectly fine.
Then it turns out to be something wrong with my application so for this I put whole lot of cout's to identify what actually is happening. With this I found that one of the xerces-c XML parsing library function is returning NULL and with this NULL reference I am trying to call a function in line below which is making my application dump as soon as it starts.
But the thing is the same function is working fine when I run my application manually on a terminal. Full application is bit big so I have created a demo code which reproduces the problem. Here is my code:
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <iostream>
using namespace std;
using namespace xercesc;
int main()
{
try
{
// init xerces XML Parser library
XMLPlatformUtils::Initialize();
}
catch (const XMLException& ex)
{
cerr << ex.getMessage() << endl;
}
// parse a XML file
XercesDOMParser* parser = new XercesDOMParser();
try
{
parser->parse("sample.xml");
}
catch (const XMLException& ex)
{
cerr << ex.getMessage() << endl;
}
// get the document reference
DOMDocument* doc = parser->getDocument();
if (doc == NULL)
{
cout <<"Doc is NULL" << endl;
}
// else do stuff further
// like get root element
DOMElement* root = doc->getDocumentElement();
// print node name
string name = XMLString::transcode(root->getTagName());
cout << "Name: " << name << endl;
XMLPlatformUtils::Terminate();
return 0;
}
The above code when compiled and ran manually does not go into that if condition which says "Doc is NULL" and successfully prints the root element tag name, but when I run this application behind inetd and when I telnet to it I am able to see "Doc is NULL" statement and after that same message "Connection closed by foreign host." as my application would be probably dumping.
I am a bit out of brains now as I am not sure where to look exactly. As same code works when ran manually but not through inetd.
So, I am thinking do we need to take some special attention while executing processes via inetd that uses shared libraries, like here I am using xerces-c shared library for XML parsing.
Or What else could be possibly wrong with my understanding or my code.
How come the same library functions works perfectly fine when application ran manually and not working when ran via inetd?
I tried the same using xinetd instead of inetd but same results.
As you have proven yourself, the working directory is / when you start your tool via inetd. But your XML file is not in the root directory of your system. You can hardwire the full path into your application. A better solution would be to pass the location of your file(s) as a parameter.
I am writing a C++ CGI application to run on IIS7. My problem is that when the volume of data sent to a POST request gets over a certain size, reading from standard input blocks forever, rather than setting EOF. I suspect this is not a C++ specific issue. I have already successfully configured the server to run a "hello world" type application which I am now extending to do something useful, so I do not feel it is a fundamental mis-configuration.
The most trivial application to illustrate the problem is as follows. The application halts on the call on the commented line (I have attached the debugger to the process running under IIS to prove this).
#include <iostream>
int main(int argc, char** argv )
{
std::stringstream input_text;
input_text << std::cin.rdbuf(); // application halts here
std::cout << "Content-type: text/xml; charset=utf-8\n\n";
return 0;
}
I have found various people discussing the same issue but no resolution e.g.
similar issue (look for the string 'It seemed that IIS7 was not filling STDIN "immediately" and if I just did a "readfile" of the whole expected number of bytes, some windows thread was getting "stuck" somewhere.)'
similar issue with Python CGI
I expect this is a basic question, but I haven't been able to find an answer.
I'm building a web server in C++, and in order to help me visualise the system as it's running I'm building a separate program to do the visualisation. The web server will inform the visualiser of its current state by printing statements to stdout that are piped into the visualiser, which will parse the input and render a nice schematic view of the whole system along with various stats. The visualiser will be written in Python.
To check that I understand how piping works I created two simple programs:
#include <iostream>
using namespace std;
int main() {
cout << "Hello world!\n";
return 0;
}
, and
#include <iostream>
using namespace std;
int main() {
char buf[128];
while (!cin.eof()) {
cin.getline(buf, 128, '\n');
cout << "Received line: " << buf << "\n";
}
return 0;
}
This works as expected when I execute the command
./one | ./two
However, when I run my web server like so:
./aril | ./two
I get no output at all.
Running the server on its own produces output like the following:
Spawning handlers
Waiting for HTTP clients
Server: got connection from 127.0.0.1, port 52168
Connection timed out
(Obviously that isn't actually the kind of output I'll be passing to the visualiser -- it will need a more easily parse-able syntax).
Possibly relevant info:
The web server is divided into two processes: aril and arild. aril runs with root privileges, whereas arild doesn't. Both processes print to stdout using std::cout.
I can't think of any reason why this isn't working.
EDIT:
The solution, it turns out, is simply to explicitly flush the output. Should have been the first thing I tried really..
Your web server is printing in STDERR while in two you are reading from STDIN. So it'll not work.
Change ./aril | ./two to
./aril 2>&1 | ./two
This will redirect all the STDERR and STOUT of aril to STDOUT and thus two will be able to read it.
It is possible that aril detects if its output is piped (see fstat() and this thread http://cboard.cprogramming.com/cplusplus-programming/73909-prevent-piping.html for details) and switches to silent mode, i.e does not produce any output. Try piping to something else, cat maybe, and see if it produces an output.
I think your programs are designed to work as pairs, but not interchangeably. ./one | ./two are an example of piping, but ./aril is expecting to communicate with ./arild via sockets. It probably doesn't make sense to mix ./aril | ./two.
I've been wondering, what is the point of clog? As near as I can tell, clog is the same as cerr but with buffering so it is more efficient. Usually stderr is the same as stdout, so clog is the same as cout. This seems pretty lame to me, so I figure I must be misunderstanding it. If I have log messages going out to the same place I have error messages going out to (perhaps something in /var/log/messages), then I probably am not writing too much out (so there isn't much lost by using non-buffered cerr). In my experience, I want my log messages up to date (not buffered) so I can help find a crash (so I don't want to be using the buffered clog). Apparently I should always be using cerr.
I'd like to be able to redirect clog inside my program. It would be useful to redirect cerr so that when I call a library routine I can control where cerr and clog go to. Can some compilers support this? I just checked DJGPP and stdout is defined as the address of a FILE struct, so it is illegal to do something like "stdout = freopen(...)".
Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
Is the only difference between clog and cerr the buffering?
How should I implement (or find) a more robust logging facility (links please)?
Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
Yes. You want the rdbuf function.
ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout << "Goes to file." << endl;
Is the only difference between clog and cerr the buffering?
As far as I know, yes.
If you're in a posix shell environment (I'm really thinking of bash), you can redirect any
file descriptor to any other file descriptor, so to redirect, you can just:
$ myprogram 2>&5
to redirect stderr to the file represented by fd=5.
Edit: on second thought, I like #Konrad Rudolph's answer about redirection better. rdbuf() is a more coherent and portable way to do it.
As for logging, well...I start with the Boost library for all things C++ that isn't in the std library. Behold: Boost Logging v2
Edit: Boost Logging is not part of the Boost Libraries; it has been reviewed, but not accepted.
Edit: 2 years later, back in May 2010, Boost did accept a logging library, now called Boost.Log.
Of course, there are alternatives:
Log4Cpp (a log4j-style API for C++)
Log4Cxx (Apache-sponsored log4j-style API)
Pantheios (defunct? last time I tried I couldn't get it to build on a recent compiler)
Google's GLog (hat-tip #SuperElectric)
There's also the Windows Event logger.
And a couple of articles that may be of use:
Logging in C++ (Dr. Dobbs)
Logging and Tracing Simplified (Sun)
Since there are several answers here about redirection, I will add this nice gem I stumbled across recently about redirection:
#include <fstream>
#include <iostream>
class redirecter
{
public:
redirecter(std::ostream & dst, std::ostream & src)
: src(src), sbuf(src.rdbuf(dst.rdbuf())) {}
~redirecter() { src.rdbuf(sbuf); }
private:
std::ostream & src;
std::streambuf * const sbuf;
};
void hello_world()
{
std::cout << "Hello, world!\n";
}
int main()
{
std::ofstream log("hello-world.log");
redirecter redirect(log, std::cout);
hello_world();
return 0;
}
It's basically a redirection class that allows you to redirect any two streams, and restore it when you're finished.
Redirections
Konrad Rudolph answer is good in regard to how to redirect the std::clog (std::wclog).
Other answers tell you about various possibilities such as using a command line redirect such as 2>output.log. With Unix you can also create a file and add another output to your commands with something like 3>output.log. In your program you then have to use fd number 3 to print the logs. You can continue to print to stdout and stderr normally. The Visual Studio IDE has a similar feature with their CDebug command, which sends its output to the IDE output window.
stderr is the same as stdout?
This is generally true, but under Unix you can setup the stderr to /dev/console which means that it goes to another tty (a.k.a. terminal). It's rarely used these days. I had it that way on IRIX. I would open a separate X-Window and see errors in it.
Also many people send error messages to /dev/null. On the command line you write:
command ...args... 2>/dev/null
syslog
One thing not mentioned, under Unix, you also have syslog().
The newest versions under Linux (and probably Mac OS/X) does a lot more than it used to. Especially, it can use the identity and some other parameters to redirect the logs to a specific file (i.e. mail.log). The syslog mechanism can be used between computers, so logs from computer A can be sent to computer B. And of course you can filter logs in various ways, especially by severity.
The syslog() is also very simple to use:
syslog(LOG_ERR, "message #%d", count++);
It offers 8 levels (or severity), a format a la printf(), and a list of arguments for the format.
Programmatically, you may tweak a few things if you first call the openlog() function. You must call it before your first call to syslog().
As mentioned by unixman83, you may want to use a macro instead. That way you can include some parameters to your messages without having to repeat them over and over again. Maybe something like this (see Variadic Macro):
// (not tested... requires msg to be a string literal)
#define LOG(lvl, msg, ...) \
syslog(lvl, msg " (in " __FILE__ ":%d)", __VA_ARGS__, __LINE__)
You may also find __func__ useful.
The redirection, filtering, etc. is done by creating configuration files. Here is an example from my snapwebsites project:
mail.err /var/log/mail/mail.err
mail.* /var/log/mail/mail.log
& stop
I install the file under /etc/rsyslog.d/ and run:
invoke-rc.d rsyslog restart
so the syslog server handles that change and saves any mail related logs to those folders.
Note: I also have to create the /var/log/mail folder and the files inside the folder to make sure it all works right (because otherwise the mail daemon may not have enough permissions.)
snaplogger (a little plug)
I've used log4cplus, which, since version 1.2.x, is quite good. I have three cons about it, though:
it requires me to completely clear everything if I want to call fork(); somehow it does not survive a fork(); call properly... (at least in the version I had it used a thread)
the configuration files (.properties) are not easy to manage in my environment where I like the administrators to make changes without modifying the original
it uses C++03 and we are now in 2019... I'd like to have at least C++11
Because of that, and especially because of point (1), I wrote my own version called snaplogger. This is not exactly a standalone project, though. I use many other projects from the snapcpp environment (it's much easier to just get snapcpp and run the bin/build-snap script or just get the binaries from launchpad.)
The advantage of using a logger such as snaplogger or log4cplus is that you generally can define any number of destinations and many other parameters (such as the severity level as offered by syslog()). The log4cplus is capable of sending its output to many different places: files, syslog, MS-Windows log system, console, a server, etc. Check out the appenders in those two projects to have an idea of the list of possibilities. The interesting factor here is that any log can be sent to all the destinations. This is useful to have a file named all.log where all your services send their logs. This allows to understand certain bugs which would not be as easy with separate log files when running many services in parallel.
Here is a simple example in a snaplogger configuration file:
[all]
type=file
lock=true
filename=/var/log/snapwebsites/all.log
[file]
lock=false
filename=/var/log/snapwebsites/firewall.log
Notice that for the all.log file I require a lock so multiple writers do not mangle the logs between each others. It's not necessary for the [file] section because I only have one process (no threads) for that one.
Both offer you a way to add your own appenders. So for example if you have a Qt application with an output window, you could write an appender to send the output of the SNAP_LOG_ERROR() calls to that window.
snaplogger also offers you a way to extend the variable support in messages (also called the format.) For example, I can insert the date using the ${date} variable. Then I can tweak it with a parameter. To only output the year, I use ${date:year}. This variable parameter support is also extensible.
snaplogger can filter the output by severity (like syslog), by a regex, and by component. We have a normal and a secure component, the default is normal. I want logs sent to the secure component to be written to secure files. This means in a sub-directory which is way more protected than the normal logs that most admins can review. When I run my HTTP services, some times I send information such as the last 3 digits of a credit card. I prefer to have those in a secure log. It could also be password related errors. Anything I deem to be a security risk in a log, really. Again, components are extensible so you can have your own.
One little point about the redirecter class. It needs to be destroyed properly, and only once. The destructor will ensure this will happen if the function it is declared in actually returns, and the object itself is never copied.
To ensure it can't be copied, provide private copy and assignment operators:
class redirecter
{
public:
redirecter(std::ostream & src, std::ostream & dst)
: src_(src), sbuf(src.rdbuf(dst.rdbuf())) {}
~redirecter() { src.rdbuf(sbuf); }
private:
std::ostream & src_;
std::streambuf * const sbuf_;
// Prevent copying.
redirecter( const redirecter& );
redirecter& operator=( const redirecter& );
};
I'm using this technique by redirecting std::clog to a log file in my main(). To ensure that main() actually returns, I place the guts of main() in a try/catch block. Then elsewhere in my program, where I might call exit(), I throw an exception instead. This returns control to main() which can then execute a return statement.
Basic Logger
#define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;}
Used as myerr("ERR: " << message); or myerr("WARN: " << message << code << etc);
Is very effective.
Then do:
./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log
or just parse stderr.log by hand
I admit this is not for extremely performance critical code. But who writes that anyway.