calling std::system with parameter containing space in double quotes - linux

I need to call a linux std::system call with parameter than contain string with spaces. In order to process it correctly using argc / argv I want to pass it with double quotes.
std::string cmdline = "myprogram -d \"I am a sting\"" ;
if I cout this string I get good results.
When I send it to std::system(cmdline)
and look at ps -ef I get
myprogram -d I am a string
How can I keep "I am a string" as a single parameter for myprogram ?

No problem:
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ cat test.cpp
#include <iostream>
#include <string>
#include <cstdlib>
int main()
{
std::string cmdline = "./see \"I am a string\"";
std::cout << cmdline << std::endl;
std::system(cmdline.c_str());
}
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ cat see.cpp
#include <iostream>
int main(int argc, char* argv[])
{
for (int i = 0; i < argc; ++i)
{
std::cout << argv[i] << std::endl;
}
}
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ g++ -std=c++11 test.cpp -o test
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ g++ -std=c++11 see.cpp -o see
dlaru#IKH-LAPTOP /cygdrive/c/Users/dlaru
$ ./test
./see "I am a string"
./see
I am a string
(tested in Cygwin)

Related

C++ string concatenation in the Windows Subsystem for Linux (WSL) is deleting first string

I need help understanding what is wrong with my code or system. For some reason, when compiled and ran in WSL(Windows Subsystem for Linux), the following code generates a wrong result. When ran directly in the windows command terminal, it correctly generates the final output as HNDPNV and in WSL generates PNV. The airports file is simply a series of 50 lines, with 3 letters per line. g++ version is 7.5.0 in ubuntu 18.04 WSL and g++ windows version is 9.2.0.
compilation flags are: g++ -std=c++17 -Wall -Wextra -o test test.cpp
#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
using namespace std;
int main() {
string airport_designations[50];
string air_companies_designations[20];
ifstream airports;
ifstream aircompanies;
string name = "apple";
string name2 = "orange";
airports.open("Airports.txt");
for (int i = 0; i < 50; i++){
getline(airports, airport_designations[i]);
cout << airport_designations[i] << endl;
}
airports.close();
aircompanies.open("Companies.txt");
for (int i = 0; i < 20; i++){
getline(aircompanies, air_companies_designations[i]);
cout << air_companies_designations[i] << endl;
}
aircompanies.close();
name = airport_designations[4];
cout << name << endl;
name += airport_designations[8];
cout << name << endl;
}
The line break on windows is \r\n,
On Linux \n.
To get a consistent conclusion, you need to replace all \r\ n in the Airports.txt file with \n.

Where are POSIX message queues located (Linux)?

man 7 mq_overview says that the POSIX "...message queues on the system can be viewed and manipulated using the commands usually used for files (e.g., ls(1) and rm(1))."
For example I was able to read using a mqd_t as a file descriptor as follows:
#include <iostream>
#include <fcntl.h>
#include <mqueue.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
std::cout << "Usage: mqgetinfo </mq_name>\n";
exit(1);
}
mqd_t mqd = mq_open(argv[1], O_RDONLY);
struct mq_attr attr;
mq_getattr(mqd, &attr);
std::cout << argv[1] << " attributes:"
<< "\nflag: " << attr.mq_flags
<< "\nMax # of msgs: " << attr.mq_maxmsg
<< "\nMax msg size: " << attr.mq_msgsize
<< "\nmsgs now in queue: " << attr.mq_curmsgs << '\n';
// Get the queue size in bytes, and any notification info:
char buf[1024];
int n = read(mqd, buf, 1023);
buf[n] = '\0';
std::cout << "\nFile /dev/mqueue" << argv[1] << ":\n"
<< buf << '\n';
mq_close(mqd);
}
Running this on msg queue /myq when it contains 5 msgs, 549 bytes gives:
$ g++ mqgetinfo.cc -o mqgetinfo -lrt
$ ./mqgetinfo /myq
/myq attributes:
flag: 0
Max # of msgs: 10
Max msg size: 8192
msgs now in queue: 5
File /dev/mqueue/myq:
QSIZE:549 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
$
Also:
$ !cat
cat /dev/mqueue/myq
QSIZE:549 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
So the file /dev/mqueue/myq has some info associated with the msg queue.
My question is: Where is the queue itself, i.e., where are the 549 bytes? I'm guessing they are in some list-type data structure internal to the kernel, but I don't see this mentioned in the man pages etc, and wondering how to find out about that..
Since the internal handling of message queues are implementation specific (not part of the standard, as it only specifies the programming interface and behaviour), I recommend you to have a look into the linux kernel source file ipc/mqueue.c and pay special attention to mqueue_create() and msg_insert() functions, as it's a good place to get started if you want to understand how message queues are implemented in the linux kernel.

Visual C++ debug output displaying ???? for non Latin (Cyrillic) characters

There is some Windows/VS setting that will let debug output in VS correctly output non Latin characters. We are interested in Cyrillic letters. What is that setting?
Too brief question. However, a solution based on this answer could help:
#include "stdafx.h"
#include <iostream>
#include <io.h>
#include <fcntl.h>
int wmain(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout
<< L"Unicode test -- Ελληνικά -- čeština -- русский язык -- Türkçesi"
<< std::endl;
for (int i = 1; i < argc; ++i)
{
std::wcout << L"param " << i << L": " << argv[i] << std::endl;
}
}
Verified using Visual Studio 2013:
==> ".\so36212399\Debug\so36212399.exe" qwertz ςερτυθ ěščřžý йцукен ğüşıöç
Unicode test -- Ελληνικά -- čeština -- русский язык -- Türkçesi
param 1: qwertz
param 2: ςερτυθ
param 3: ěščřžý
param 4: йцукен
param 5: ğüşıöç
==>

libiconv on windows/linux issue

I need to perform character set conversion using iconv on windows. In this case this is transliteration to remove accents, etc. but the issue I am facing is the same for most any target encoding. Here is my Program:
#include "stdafx.h"
#include <vector>
#include <fstream>
#include <iconv.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
std::ifstream ifs("test.txt", std::ios::binary | std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();
char * pIn = new char[(int)pos + 1];
ifs.seekg(0, std::ios::beg);
ifs.read(pIn, pos);
pIn[pos] = 0;
size_t srclen = strlen(pIn);
char dst[1000];
char * pOut = (char*)dst;
size_t dstlen = 1000;
iconv_t conv = iconv_open("UTF-8", "ASCII//TRANSLIT");
std::cout << srclen << " " << dstlen << std::endl;
auto ret = iconv(conv, (const char**)&pIn, &srclen, &pOut, &dstlen);
std::cout << (int)ret << " " << errno << " " << srclen << " " << dstlen << std::endl;
iconv_close(conv);
return 0;
}
The test.txt file looks like this (UTF-8 w/o BOM):
qwe
Tøyenbekken
Zażółć gęślą jaźń
ZAŻÓŁĆ GĘŚLĄ JAŹŃ
Unfortunately the iconv call stops processing at the first non ASCII character and program outputs:
75 1000
-1 0 69 994
The return value of -1 indicates error, but errno is set to 0 which gives no clue as to what may be wrong.
Any idea what am I doing wrong here? To make the matter more interesting here is the output of iconv.exe located in the same dir as the libiconv2.dll file:
> iconv -f utf-8 -t ascii//translit test.txt
qwe
Toyenbekken
Zaz'ol'c ge'sla ja'z'n
ZAZ'OL'C GE'SLA JA'Z'N
which is ok.
Update after testing on Linux:
The command line version of iconv does not work - it outputs some garbage to the console (in place of non ascii characters).
Using my own code it outputs error code of 84 (which is I guess EILSEQ - Illegal byte sequence) after processing ascii characters.
Any ideas what may be wrong here?
The issue was that I wanted to convert from UTF-8 to ASCII and opened the converter this way:
iconv_t conv = iconv_open("UTF-8", "ASCII//TRANSLIT");
whereas it should be done this way:
iconv_t conv = iconv_open("ASCII//TRANSLIT", "UTF-8");
(argument order). Still not sure why I did not get proper error code.

clang analyzer memory leaks

Why doesn't clang/clang-analyzer catch that I forgot to free a and have a memory leak? It's obvious. I looked at the man pages and i'm not sure what flags are required.
$ scan-build clang++ -std=c++11 a.cpp
scan-build: Using '/usr/bin/clang' for static analysis
scan-build: Removing directory '/tmp/scan-build-2013-10-02-2' because it contains no reports.
$ cat ./a.cpp
#include <iostream>
int main() {
int *a = new int;
*a = 8;
std::cout<< a << std::endl;
}

Resources