C++: Getline ignores "\n" in mqtt message - c++

I use a mqtt message to send messages like this: mosquitto_pub -t "TOPIC1" -m "ARG1\nARG2\n"
In my C++ application i write:
string payload = reinterpret_cast<char*>(message->payload);
std::istringstream iss(payload);
std::string arg1;
std::getline(iss, arg1);
cout << arg1 << endl;
This gives me ARG1\nARG2\n. What's wrong here?

This is not a C++ problem.
Your problem is that normally \n is not interpreted as new line in by bash for a command line argument. Also mosquitto_pub will not do any interpretation on the input message.
You can force this as follows:
mosquitto_pub -t "TOPIC1" -m $'ARG1\nARG2\n'

Related

Popen giving some strange character in output when running multiple command in it

I write code to fetch the fragmented packet by using a unique Identification field from pcap file. So I run scripting command in my C++ program.
First tshark command will fetch all the identification field from the packet with the callID mentioned in the filter and the second one will fetch all the fragmented packet identification field in that pcap.
And awk command compare then and find the unique identification field present in both the tshark command output.
Command will be like---
cmd = (awk 'FNR==NR{a[$0]=1;next}($0 in a)' <((/usr/sbin/tshark -r
/data/traces/TRACES.pcap 'sip.Call-ID=="1-4740#10.133.0.1" or
sip.Call-ID=="57b116c-5b20924e-93dcd"' -T fields -e ip.id)
2>/dev/null) <((/usr/sbin/tshark -r /data/traces/TRACES.pcap
'ip.flags.mf==1' -T fields -e ip.id) 2>/dev/null)) 2>/dev/null
Reading data by
FILE * stream = popen(cmd.c_str(), "r");
if (!stream)
{
LOG_DEBUG("popen failed");
}
fflush(stream);
NOTE:: I tried with fflush and without fflush still giving me strange
character.
while(fgets(buffer, 40, stream) != NULL)
{
data = buffer;
result += data + '\n';
}
if(data.empty()) {
data = buffer;
result = data + '\0';
}
NOTE:: Tried with the system() command also but this also returns me a strange Character
OUTPUT will be like --> 0^_iÏO^?
I notice a strange thing that when I execute tshark command individually and save the output in a different file and then using awk command on that files then it will give the correct output.
And Command is correctly running in the terminal also.

QThread doesn't provide output from called shellscript

I have a function that executes system calls and writes the output into a QTextEdit.
string SystemCallFactory::runSysCallWithoutButton(unique_ptr<SystemCall> sysCall)
{
cout << "Running " << sysCall->getCommand() << endl;
textEdit->setText("");
textEdit->repaint();
QProcess process;
process.start(QString::fromStdString(sysCall->getCommand()));
process.waitForFinished();
QString output(process.readAllStandardOutput());
textEdit->append(output);
textEdit->repaint();
return output.toStdString();
}
The problem is that this works when getCommand() is a real command, e.g. ls /etc but does not work correctly when it refers to a shellscript. In my calls, the call that does not work looks like
/home/turtle10000/tilematching.sh /some/folder /some/specific.file
The script gets executed and does what it's supposed to do, but readAllStandardOutput() returns an empty string. When I run it in a terminal, it shows the expected output.
This is the shellscript:
#!/bin/sh -v
WORKSPACE=$1
SVPFILE=$2
cd $WORKSPACE
ls -1 *.all > datalist.0.mb-1
mbset -I datalist.0.mb-1 -PSVPMODE:1 -PSVPFILE:$SVPFILE
mbprocess -I datalist.0.mb-1
ls -1 *p.mb58 > datalist.1.mb-1
mbset -I datalist.1.mb-1 -PSONAROFFSETX:-0.079 -PSONAROFFSETY:0.196 -PSONAROFFSETZ:0.048 -PVRUOFFSETX:-0.4473 -PVRUOFFSETY:0.000 -PVRUOFFSETZ:-0.3395 -PROLLBIAS:0.1 -PPITCHBIAS:1.32
mbprocess -I datalist.1.mb-1
ls -1 *pp.mb58 > datalist.2.mb-1
mblist -I datalist.2.mb-1 -MA -O^X^Y-z -JU > output.xyz
#remove broken lines (error in input files)
sed -ie '/ /d' output.xyz
Edit: as Botje guessed, some of output appears in stderr instead of stdout.
As Botje suggested, I checked if the output went to stderr and it did. For whatever reason, the output of mbset and mbprocess, tools from the mb-system package, goes to stderr.
In this case, I changed the line
QString output(process.readAllStandardOutput());
to
QString output(process.readAllStandardError());
Another option would probably be to channel the stderr output to stdout in the script.

(Qt) Curl uploading to smtp sends an empty email

I'm using Qt and I recently made a similar application using gmail. Now, I want to send the email from outlook to gmail. EDIT: I just tried sending from outlook to outlook using an app password but still empty email in my outlook inbox... END EDIT Here is my code:
if(file.open(QIODevice::ReadWrite)){ //Writes in the msg.txt
QTextStream stream(&file);
stream << "From: \"Me\" <xxxxxxxxxx#outlook.com>" << endl;
stream << "To: \"Me\" <xxxxxxxxxxxx#gmail.com>" << endl;
stream << "Subject: Subject" << endl;
stream << msg << endl; //msg is just a QString variable
}
QString cmd = "ccurl smtp://smtp-mail.outlook.com:587 -v --mail-from \"xxxxxxxxxxxx#outlook.com\" --mail-rcpt \"xxxxxxxxxxxx#gmail.com\" --ssl -u xxxxxxxxxxxxxx#outlook.com:xxxxxxxxxxxxxx -T \"msg.txt\" -k --anyauth --insecure & pause";
const std::string s = cmd.toStdString();
const char* ccmd = s.c_str();
system(ccmd);
Pause is just used for testing purposes. Also, my .exe is named 'ccurl' and the console that appears doesn't throw any error. I do receive an email but it just says something like (Empty)
---
Email checked by avast....
Thanks for your help!
Ps. Don't tell me to use libcurl instead
You are missing an empty line between the end of the headers and the start of the message body. Without it, the rest of the message is interpreted as if it was still part of the headers.
Also, endl forces a flush in the stream for no good reason, which kills performance when done on files. Just use \n.

c++ run curl in shell via system

If I write this in my shell, everything works like a charme:
// shell (unix)
curl -X PUT -d "{ \"string\" : \"my string 1212 \"}" "https://my.firebaseio.com/myVal.json"
As you can tell, this inserts some stuff in my firebase. As mentioned above, this works as expected. Since I am not too deep in C++, I have no idea on how to PUT curl-requests internally. I was thinking about doing it in the shell via system.
I ended up with this:
// c++ code
system('curl -X PUT -d "{ \"string\" : \"my string 1212 \"}" "https://my.firebaseio.com/myVal.json" ');
This however produces this output:
curl: (6) Could not resolve host:
curl: (6) Could not resolve host: CD
curl: (7) Could not resolve host: CD
curl: (3) [globbing] unmatched close brace/bracket in column 1
Thanks for any helpful advices
// Update 1
After hearing that single quotes ' are reserved for chars and going for the solution erip provided, it is still the same output:
curl: (6) Could not resolve host:
curl: (6) Could not resolve host: cd
curl: (7) Could not resolve host: cd
curl: (3) [globbing] unmatched close brace/bracket in column 1
{
"error" : "Invalid data; couldn't parse JSON object, array, or value. Perhaps you're using invalid characters in your key names."
}
In C++, single quotes are used for the type char. Double quotes are reserved for std::strings or char *s.
Thus, your solution should be by simply replacing single quotes with double quotes and escaping the quotes that aren't your final quote:
system("curl -X PUT -d \"{ \"string\" : \"my string 1212 \"}\" https://my.firebaseio.com/myVal.json ");
However, like #DaoWen mentioned, always use a library if/when possible.
EDIT
I'd recommend trying this:
std::string command = "curl -X PUT -d \"{ \"string\" : \"my string 1212 \"}\" https://my.firebaseio.com/myVal.json ";
system(command.c_str());
But honestly, it's better to use fork and exec calls than system calls if you don't want to use libcurl.
EDIT 2
std::string command = "curl -H \"Content-Type: application/json\" -X PUT -d '{ \"string\" : \"my string 1212 \"}' https://my.firebaseio.com/myVal.json";
system(command.c_str());
The weird escaped quotes were treating key: "string" as the host because { was surrounded by quotes, acting as the data. I fixed this by surrounding the data to be passed with a single quote.
You can see that I PUT { "Hello" : "World!" } to your app here.
Hope this helped.

Avoid line return when calling AINSI escape sequence

I made this function who change the title of a terminal window by using ainsi escape sequence but after the call of this function a line is jumped in console, how avoid this ?
void setConsoleTitle(std::string const& title)
{
m_title = title;
std::string cmd1 = "echo \"\033]0;";
cmd1 += title;
cmd1 += "\007\"";
system(cmd1.c_str());
}
Thanks.
ReallY DON'T use system here (it starts a new process, in which a shell is run, and then runs echo in that shell, and tears down that new process - which is a lot of work to output a handful of characters to the screen, that can just as well be output with cout or similar - system is acceptable to use if you, say, need to run a compiler or unpack a zip file - something that isn't easy to do in your own program). But if you insist on using system, then use echo -n ..., where man echo explains it as:
-n do not output the trailing newline
However, just using cout will do fine here:
cout << "\033]0;" << title << "\a";
(\a is "alarm", the same as \007 but portable in case your system doesn't use character number 7 for "ring the bell")
Why you want to print "noise" is beyond me, but the above does the same thing as your "echo" command.