<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>POSIX popen and ARG_MAX</title>
		<link>http://www.allegro.cc/forums/view/616818</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Fri, 31 Mar 2017 20:14:16 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Does popen leak file descriptors to the command it executes? For example, I call curl with popen and end it with &amp; ampersand so that my main process would immediately continue without waiting for curl to finish.</p><p>How to programmatically find out what is the maximum argument length popen can handle? ARG_MAX is not it because when I tested this popen was failing already with argument length of ARG_MAX/30.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Sat, 25 Mar 2017 20:48:12 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>popen does not execute the command directly. If it did, &quot;&amp;&quot; would have no meaning. The command is being interpreted by /bin/sh -c. I wonder if your command would be killed by -c if not also disowned by the sh process? I&#39;m not sure.</p><p>In glibc popen is basically just calling __execve, which as far as I can tell is just the system call implemented in the kernel in Linux. The only thing I saw in glibc is that if the <i>number of arguments</i> passed is greater than INT_MAX then it will error out. That&#39;s a minimum of 2-billion and change so unless you have a very exceptional command that likely isn&#39;t being hit.</p><p>The only information I could find was that it used to be based on ARG_MAX (in my Linux system that is defined as 128 kB) or on MAX_ARG_PAGES, which is apparently 32. With 4 kB pages that again yields 128 kB. That also includes the size of the environment so keep that in mind. These days it&#39;s based on 1/4 of RLIMIT_STACK, which is the stack size limit for a process. I don&#39;t know what that is, but I would guess it&#39;s in the hundreds of MiB or GiB (depending on your hardware and architecture probably). Of course, it would take out of the space available to the program for its stack, but again it seems unlikely you&#39;d reach any of these limits. This is all specific to Linux though. You haven&#39;t told us which OS you&#39;re using.</p><p>The question is, how long <i>is</i> your command (keep in mind there is an additional size of &quot;/bin/sh -c &quot; added in the case of popen)? And how do you know that it&#39;s failing because of the length of the command? It might help if you tell us exactly what errors or return codes you&#39;re getting.</p><p><b>Append:</b></p><div class="source-code"><div class="toolbar"><span class="name">sleep.c</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="p">#include &lt;stdio.h&gt;</span>
<span class="number">  2</span><span class="p">#include &lt;stdlib.h&gt;</span>
<span class="number">  3</span><span class="p">#include &lt;string.h&gt;</span>
<span class="number">  4</span><span class="p">#include &lt;unistd.h&gt;</span>
<span class="number">  5</span>
<span class="number">  6</span><span class="k1">int</span> main<span class="k2">(</span><span class="k1">int</span> argc, <span class="k1">char</span> <span class="k3">*</span> argv<span class="k2">[</span><span class="k2">]</span><span class="k2">)</span>
<span class="number">  7</span><span class="k2">{</span>
<span class="number">  8</span>    <span class="k1">int</span> remaining, timeout<span class="k2">;</span>
<span class="number">  9</span>
<span class="number"> 10</span>    <span class="k1">if</span> <span class="k2">(</span>argc <span class="k3">&lt;</span> <span class="n">2</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 11</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_348.html" target="_blank">fputs</a><span class="k2">(</span><span class="s">"Too few arguments.\n"</span>, stderr<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 12</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 13</span>    <span class="k2">}</span>
<span class="number"> 14</span>
<span class="number"> 15</span>    timeout <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_54.html" target="_blank">atoi</a><span class="k2">(</span>argv<span class="k2">[</span><span class="n">1</span><span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 16</span>
<span class="number"> 17</span>    sleep_: remaining <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_731.html" target="_blank">sleep</a><span class="k2">(</span>timeout<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 18</span>
<span class="number"> 19</span>    <span class="k1">if</span> <span class="k2">(</span>remaining <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 20</span>        timeout <span class="k3">=</span> remaining<span class="k2">;</span>
<span class="number"> 21</span>        <span class="k1">goto</span> sleep_<span class="k2">;</span>
<span class="number"> 22</span>    <span class="k2">}</span>
<span class="number"> 23</span>
<span class="number"> 24</span>    <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span>
<span class="number"> 25</span><span class="k2">}</span>
</div></div><p>

</p><div class="source-code"><div class="toolbar"><span class="name">main.c</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="p">#include &lt;errno.h&gt;</span>
<span class="number">  2</span><span class="p">#include &lt;stdio.h&gt;</span>
<span class="number">  3</span><span class="p">#include &lt;stdlib.h&gt;</span>
<span class="number">  4</span><span class="p">#include &lt;string.h&gt;</span>
<span class="number">  5</span>
<span class="number">  6</span><span class="k1">int</span> main<span class="k2">(</span><span class="k1">int</span> argc, <span class="k1">char</span> <span class="k3">*</span> argv<span class="k2">[</span><span class="k2">]</span><span class="k2">)</span>
<span class="number">  7</span><span class="k2">{</span>
<span class="number">  8</span>    FILE <span class="k3">*</span> handle <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span><span class="s">"./sleep 3500 &amp;"</span>, <span class="s">"w"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  9</span>
<span class="number"> 10</span>    <span class="k1">if</span> <span class="k2">(</span>handle <span class="k3">=</span><span class="k3">=</span> NULL<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 11</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_345.html" target="_blank">fprintf</a><span class="k2">(</span>stderr, <span class="s">"Failed to ^Z cat fork. (%d)\n"</span>, <a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 12</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 13</span>    <span class="k2">}</span>
<span class="number"> 14</span>
<span class="number"> 15</span>    <span class="k1">int</span> ret <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>handle<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 16</span>
<span class="number"> 17</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_345.html" target="_blank">fprintf</a><span class="k2">(</span>stderr, <span class="s">"./sleep returned %d\n"</span>, ret<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 18</span>
<span class="number"> 19</span>    <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span>
<span class="number"> 20</span><span class="k2">}</span>
</div></div><p>

The program immediately returns.</p><pre class="terminal">$ gcc -o sleep -Wall sleep.c
$ gcc -o main -Wall main.c
$ ./main
./sleep returned 0</pre><p>

I think that the &#39;&amp;&#39; is causing &#39;sh -c&#39; to halt it immediately. My sh is dash and the manpage only says that if the shell is not interactive then stdin is set to /dev/null. I don&#39;t think that should cause this behavior so I&#39;m not sure.</p><p><b>Append:</b></p><p>OK, here we go. Now I see. If I list processes with ps then &quot;./sleep 3500&quot; is still running. That makes a bit of sense. You told sh to background it so it did just that. sh was non-interactive so it exited normally. ./sleep is left running doing its thing. If you need control of those curl processes so they can&#39;t be left behind like this then you should probably not be using popen. You may need to use fork and exec or something like that to achieve this properly.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Sun, 26 Mar 2017 11:41:37 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;m programming it on Linux Mint but ideally it should be POSIX compliant. Below is the problematic function. I just added spaces at the end of the cfg parameter before calling str2hex on it. At some point the command didn&#39;t execute properly because netcat didn&#39;t respond me with anything.</p><p>Ideally I&#39;d like to programmatically find out the maximum length of a single argument given to popen as the command to execute because then I could implement a fallback to named pipes.</p><div class="source-code"><div class="toolbar"><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="k1">void</span> TREASURER::bitcoin_rpc<span class="k2">(</span><span class="k1">const</span> <span class="k1">char</span> <span class="k3">*</span>method, <span class="k1">const</span> nlohmann::json<span class="k3">*</span> params<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  2</span>    <span class="c">/*</span>
<span class="number">  3</span><span class="c">     *  Instead of making a blocking cURL request here we are spawning a child</span>
<span class="number">  4</span><span class="c">     *  process with popen so that we can carry on with the main program while</span>
<span class="number">  5</span><span class="c">     *  the request is being executed. When the child process finishes it will</span>
<span class="number">  6</span><span class="c">     *  connect back to the main server providing us the response from Bitcoin RPC.</span>
<span class="number">  7</span><span class="c">     *  This clever trick achieves asynchronous HTTP requests without using threads</span>
<span class="number">  8</span><span class="c">     *  in our main process.</span>
<span class="number">  9</span><span class="c">     */</span>
<span class="number"> 10</span>    <span class="k1">if</span> <span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> nullptr<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 11</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute Bitcoin RPC '%s': cookie not found."</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 12</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 13</span>    <span class="k2">}</span>
<span class="number"> 14</span>
<span class="number"> 15</span>    nlohmann::json json<span class="k2">;</span>
<span class="number"> 16</span>    json<span class="k2">[</span><span class="s">"jsonrpc"</span><span class="k2">]</span> <span class="k3">=</span> <span class="s">"1.0"</span><span class="k2">;</span>
<span class="number"> 17</span>    json<span class="k2">[</span><span class="s">"id"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number"> 18</span>    json<span class="k2">[</span><span class="s">"method"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number"> 19</span>    <span class="k1">if</span> <span class="k2">(</span>params<span class="k2">)</span> json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> <span class="k3">*</span>params<span class="k2">;</span>
<span class="number"> 20</span>    <span class="k1">else</span>        json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> nlohmann::json::array<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 21</span>    <span class="c">//std::cout &lt;&lt; json.dump(4) &lt;&lt; std::endl;</span>
<span class="number"> 22</span>
<span class="number"> 23</span>    std::string cfg<span class="k2">;</span>
<span class="number"> 24</span>    cfg.append<span class="k2">(</span><span class="s">"--url http://127.0.0.1:8332/\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 25</span>    cfg.append<span class="k2">(</span><span class="s">"--max-time 10\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 26</span>    cfg.append<span class="k2">(</span><span class="s">"-u "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 27</span>    cfg.append<span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 28</span>    cfg.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\n'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 29</span>    cfg.append<span class="k2">(</span><span class="s">"-H \"content-type: text/plain;\"\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 30</span>    cfg.append<span class="k2">(</span><span class="s">"--data-binary @-\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 31</span>    cfg.append<span class="k2">(</span>json.dump<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 32</span>
<span class="number"> 33</span>    std::string hex<span class="k2">;</span>
<span class="number"> 34</span>    str2hex<span class="k2">(</span>cfg.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="k3">&amp;</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 35</span>
<span class="number"> 36</span>    std::string command <span class="k3">=</span> <span class="s">"printf \"%s\" \""</span><span class="k2">;</span>
<span class="number"> 37</span>    command.append<span class="k2">(</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 38</span>    command.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\"'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 39</span>    command.append<span class="k2">(</span><span class="s">" | xxd -p -r "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 40</span>    command.append<span class="k2">(</span><span class="s">" | curl -s --config - "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 41</span>    command.append<span class="k2">(</span><span class="s">" | xargs -0 printf 'su\nsend "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 42</span>    command.append<span class="k2">(</span>std::to_string<span class="k2">(</span>id<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 43</span>    command.append<span class="k2">(</span><span class="s">" %s\nexit\nexit\n'"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 44</span>    command.append<span class="k2">(</span><span class="s">" | netcat -q -1 localhost "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 45</span>    command.append<span class="k2">(</span>manager-&gt;get_tcp_port<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 46</span>    command.append<span class="k2">(</span><span class="s">" &gt; /dev/null 2&gt;/dev/null &amp;"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 47</span>
<span class="number"> 48</span>    FILE <span class="k3">*</span>fp <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span>command.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="s">"r"</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Open the command for reading.</span>
<span class="number"> 49</span>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>fp<span class="k2">)</span> manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute '%s'.\n"</span>, command.c_str<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 50</span>    <span class="k1">else</span> <span class="k2">{</span>
<span class="number"> 51</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>fp<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 52</span>        manager-&gt;vlog<span class="k2">(</span><span class="s">"Bitcoin RPC ---&gt; %s"</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 53</span>    <span class="k2">}</span>
<span class="number"> 54</span><span class="k2">}</span>
</div></div><p>

I would prefer to avoid calling fork and pipe myself here because I use signals and I don&#39;t want to drive up the code complexity if it&#39;s not absolutely needed.</p><p>edit:<br />The below resource indicates that there&#39;s MAX_ARG_STRLEN which is 131072<br /><a href="https://www.in-ulm.de/~mascheck/various/argmax/">https://www.in-ulm.de/~mascheck/various/argmax/</a></p><p>This number looks suspiciously similar to the approximate command length that caused popen to fail. ARG_MAX is 2097152 in my system. When I divide it with 20 I get 104857 which is the kind of length where popen failed in my tests.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Sun, 26 Mar 2017 22:37:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Maybe it would help to split up the command into a few different steps. I&#39;ve gathered and hacked up this little program to assist with both writing and reading to a program as a pipe. Might be helpful with such a large pipeline.</p><div class="source-code"><div class="toolbar"><span class="name">popen2.h</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number"> 1</span><span class="p">#ifndef POPEN2</span>
<span class="number"> 2</span>    <span class="p">#define POPEN2</span>
<span class="number"> 3</span>
<span class="number"> 4</span><span class="k1">int</span> popen2<span class="k2">(</span><span class="k1">char</span> <span class="k3">*</span>, <span class="k1">char</span> <span class="k3">*</span> <span class="k1">const</span> <span class="k2">[</span><span class="k2">]</span>, <span class="k1">int</span> <span class="k3">*</span>, <span class="k1">int</span> <span class="k3">*</span>, <span class="k1">int</span> <span class="k3">*</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 5</span>
<span class="number"> 6</span><span class="p">#endif</span>
</div></div><p>
</p><div class="source-code"><div class="toolbar"><span class="name">popen.c</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="p">#include &lt;errno.h&gt;</span>
<span class="number">  2</span><span class="p">#include &lt;stdio.h&gt;</span>
<span class="number">  3</span><span class="p">#include &lt;stdlib.h&gt;</span>
<span class="number">  4</span><span class="p">#include &lt;string.h&gt;</span>
<span class="number">  5</span><span class="p">#include &lt;unistd.h&gt;</span>
<span class="number">  6</span>
<span class="number">  7</span><span class="k1">static</span> <span class="k1">void</span> close_pipe<span class="k2">(</span><span class="k1">int</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_616.html" target="_blank">pipe</a><span class="k2">[</span><span class="n">2</span><span class="k2">]</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  8</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_616.html" target="_blank">pipe</a><span class="k2">[</span><span class="n">0</span><span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  9</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_616.html" target="_blank">pipe</a><span class="k2">[</span><span class="n">1</span><span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 10</span><span class="k2">}</span>
<span class="number"> 11</span>
<span class="number"> 12</span><span class="k1">static</span> <span class="k1">int</span> dual_pipe<span class="k2">(</span> <span class="k1">int</span> pipe_lhs<span class="k2">[</span><span class="n">2</span><span class="k2">]</span>,
<span class="number"> 13</span>    <span class="k1">int</span> pipe_rhs<span class="k2">[</span><span class="n">2</span><span class="k2">]</span><span class="k2">)</span>
<span class="number"> 14</span><span class="k2">{</span>
<span class="number"> 15</span>    <span class="k1">int</span> i, l<span class="k2">;</span>
<span class="number"> 16</span>
<span class="number"> 17</span>    <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_616.html" target="_blank">pipe</a><span class="k2">(</span>pipe_lhs<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 18</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_615.html" target="_blank">perror</a><span class="k2">(</span><span class="s">"pipe"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 19</span>        <span class="k1">return</span> <span class="k3">-</span><span class="n">1</span><span class="k2">;</span>
<span class="number"> 20</span>    <span class="k2">}</span>
<span class="number"> 21</span>
<span class="number"> 22</span>    <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_616.html" target="_blank">pipe</a><span class="k2">(</span>pipe_rhs<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 23</span>        close_pipe<span class="k2">(</span>pipe_lhs<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 24</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_615.html" target="_blank">perror</a><span class="k2">(</span><span class="s">"pipe"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 25</span>        <span class="k1">return</span> <span class="k3">-</span><span class="n">1</span><span class="k2">;</span>
<span class="number"> 26</span>    <span class="k2">}</span>
<span class="number"> 27</span>
<span class="number"> 28</span>    <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span>
<span class="number"> 29</span><span class="k2">}</span>
<span class="number"> 30</span>
<span class="number"> 31</span><span class="k1">int</span> popen2<span class="k2">(</span> 
<span class="number"> 32</span>        <span class="k1">const</span> <span class="k1">char</span> <span class="k3">*</span> command,
<span class="number"> 33</span>        <span class="k1">char</span> <span class="k3">*</span> <span class="k1">const</span> argv<span class="k2">[</span><span class="k2">]</span>,
<span class="number"> 34</span>        <span class="k1">int</span> <span class="k3">*</span> pid,
<span class="number"> 35</span>        <span class="k1">int</span> <span class="k3">*</span> infd,
<span class="number"> 36</span>        <span class="k1">int</span> <span class="k3">*</span> outfd<span class="k2">)</span>
<span class="number"> 37</span><span class="k2">{</span>
<span class="number"> 38</span>    <span class="k1">int</span> pipe_lhs<span class="k2">[</span><span class="n">2</span><span class="k2">]</span><span class="k2">;</span>
<span class="number"> 39</span>    <span class="k1">int</span> pipe_rhs<span class="k2">[</span><span class="n">2</span><span class="k2">]</span><span class="k2">;</span>
<span class="number"> 40</span>
<span class="number"> 41</span>    <span class="k1">if</span> <span class="k2">(</span>dual_pipe<span class="k2">(</span>pipe_lhs, pipe_rhs<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 42</span>        <span class="k1">return</span> <span class="k3">-</span><span class="n">1</span><span class="k2">;</span>
<span class="number"> 43</span>    <span class="k2">}</span>
<span class="number"> 44</span>
<span class="number"> 45</span>    <span class="k3">*</span>pid <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_338.html" target="_blank">fork</a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 46</span>
<span class="number"> 47</span>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">*</span>pid <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 48</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_615.html" target="_blank">perror</a><span class="k2">(</span><span class="s">"fork"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 49</span>        <span class="k1">return</span> <span class="k3">-</span><span class="n">1</span><span class="k2">;</span>
<span class="number"> 50</span>    <span class="k2">}</span>
<span class="number"> 51</span>
<span class="number"> 52</span>    <span class="c">// Parent.</span>
<span class="number"> 53</span>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">*</span>pid<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 54</span>        <span class="k3">*</span>infd <span class="k3">=</span> pipe_lhs<span class="k2">[</span><span class="n">1</span><span class="k2">]</span><span class="k2">;</span>
<span class="number"> 55</span>        <span class="k3">*</span>outfd <span class="k3">=</span> pipe_rhs<span class="k2">[</span><span class="n">0</span><span class="k2">]</span><span class="k2">;</span>
<span class="number"> 56</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>pipe_lhs<span class="k2">[</span><span class="n">0</span><span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 57</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>pipe_rhs<span class="k2">[</span><span class="n">1</span><span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 58</span>
<span class="number"> 59</span>        <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span>
<span class="number"> 60</span>    <span class="k2">}</span>
<span class="number"> 61</span>
<span class="number"> 62</span>    <span class="c">// Child.</span>
<span class="number"> 63</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_282.html" target="_blank">dup2</a><span class="k2">(</span>pipe_lhs<span class="k2">[</span><span class="n">0</span><span class="k2">]</span>, <span class="n">0</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 64</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_282.html" target="_blank">dup2</a><span class="k2">(</span>pipe_rhs<span class="k2">[</span><span class="n">1</span><span class="k2">]</span>, <span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 65</span>    close_pipe<span class="k2">(</span>pipe_lhs<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 66</span>    close_pipe<span class="k2">(</span>pipe_rhs<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 67</span>
<span class="number"> 68</span>    execvp<span class="k2">(</span>command, argv<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 69</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_345.html" target="_blank">fprintf</a><span class="k2">(</span>stderr, <span class="s">"error running %s: %s\n"</span>, command, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 70</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_37.html" target="_blank">abort</a><span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 71</span><span class="k2">}</span>
</div></div><p>
</p><div class="source-code"><div class="toolbar"><span class="name">main.c</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="p">#include &lt;stdio.h&gt;</span>
<span class="number">  2</span><span class="p">#include &lt;stdlib.h&gt;</span>
<span class="number">  3</span><span class="p">#include &lt;unistd.h&gt;</span>
<span class="number">  4</span>
<span class="number">  5</span><span class="p">#include "popen2.h"</span>
<span class="number">  6</span>
<span class="number">  7</span><span class="p">#define buf_length (sizeof(buf)/sizeof(char))</span>
<span class="number">  8</span>
<span class="number">  9</span><span class="k1">int</span> main<span class="k2">(</span><span class="k1">int</span> argc, <span class="k1">char</span> <span class="k3">*</span> argv<span class="k2">[</span><span class="k2">]</span><span class="k2">)</span>
<span class="number"> 10</span><span class="k2">{</span>
<span class="number"> 11</span>    <span class="k1">char</span> buf<span class="k2">[</span><span class="n">50</span><span class="k2">]</span><span class="k2">;</span>
<span class="number"> 12</span>    <span class="k1">char</span> <span class="k3">*</span> <span class="k1">const</span> tee_argv<span class="k2">[</span><span class="k2">]</span> <span class="k3">=</span> <span class="k2">{</span><span class="s">"tee"</span><span class="k2">}</span><span class="k2">;</span>
<span class="number"> 13</span>    <span class="k1">int</span> len, pid, infd, outfd<span class="k2">;</span>
<span class="number"> 14</span>
<span class="number"> 15</span>    <span class="k1">if</span> <span class="k2">(</span>popen2<span class="k2">(</span>tee_argv<span class="k2">[</span><span class="n">0</span><span class="k2">]</span>, tee_argv, <span class="k3">&amp;</span>pid, <span class="k3">&amp;</span>infd, <span class="k3">&amp;</span>outfd<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 16</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a><span class="k2">(</span><span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 17</span>    <span class="k2">}</span>
<span class="number"> 18</span>
<span class="number"> 19</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_866.html" target="_blank">write</a><span class="k2">(</span>infd, <span class="s">"Hello\n"</span>, <span class="n">6</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 20</span>
<span class="number"> 21</span>    len <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_642.html" target="_blank">read</a><span class="k2">(</span>outfd, buf, buf_length <span class="k3">-</span> <span class="n">1</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 22</span>
<span class="number"> 23</span>    buf<span class="k2">[</span>len<span class="k2">]</span> <span class="k3">=</span> <span class="s">'\0'</span><span class="k2">;</span>
<span class="number"> 24</span>
<span class="number"> 25</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a><span class="k2">(</span><span class="s">"%s says: %s"</span>, tee_argv<span class="k2">[</span><span class="n">0</span><span class="k2">]</span>, buf<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 26</span>
<span class="number"> 27</span>    <span class="k1">if</span><span class="k2">(</span><span class="k3">!</span>len <span class="k3">|</span><span class="k3">|</span> buf<span class="k2">[</span>len <span class="k3">-</span> <span class="n">1</span><span class="k2">]</span> <span class="k3">!</span><span class="k3">=</span> <span class="s">'\n'</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 28</span>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_629.html" target="_blank">putchar</a><span class="k2">(</span><span class="s">'\n'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 29</span>    <span class="k2">}</span>
<span class="number"> 30</span>
<span class="number"> 31</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>infd<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 32</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>outfd<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 33</span>
<span class="number"> 34</span>    <span class="k1">return</span> <span class="n">0</span><span class="k2">;</span>
<span class="number"> 35</span><span class="k2">}</span>
</div></div><p>
</p><pre class="terminal">$ gcc -c -g -o popen2.o -Wall popen2.c
$ gcc -c -g -o main.o -Wall main.c
$ gcc -g -o popen2 -Wall popen2.o main.o
$ ./popen2
tee says: Hello</pre><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Mon, 27 Mar 2017 04:53:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>@bamccaig</p><p>your solution seems attractive. I&#39;m worried about fork though because I don&#39;t know exactly how to use it safely. Should I block all signals before calling fork or pipe?</p><p>edit:<br />Also, should I be using FD_CLOEXEC when calling popen?</p><div class="quote_container"><div class="title"><a href="http://man7.org/linux/man-pages/man3/popen.3.html">Quote</a>:</div><div class="quote"><p>
The type argument is a pointer to a null-terminated string which must<br />contain either the letter &#39;r&#39; for reading or the letter &#39;w&#39; for<br />writing.  Since glibc 2.9, this argument can additionally include the<br />letter &#39;e&#39;, which causes the close-on-exec flag (FD_CLOEXEC) to be<br />set on the underlying file descriptor; see the description of the<br />O_CLOEXEC flag in open(2) for reasons why this may be useful.
</p></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Mon, 27 Mar 2017 11:52:07 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;m uncertain about the importance of FD_CLOEXEC. It almost sounds like it should almost always be on by default for popen. Unless you happened to be popening a special command that expected that file descriptor to be open...</p><p>I think it&#39;s safe to use it here, but I think that&#39;s also a Linux extension so it will make the program less portable I think, which you expressed as one of your goals. The alternative, I think, would require you to wrap the program you wanted to run (e.g., curl) in a wrapper program or script that closes that file descriptor first. That said, I think that the called program would have to operate on a file descriptor that it didn&#39;t open for it to be affected, and it would be getting a file descriptor to one of its stdin/stdout handles anyway so it&#39;s probably pretty harmless...</p><p>Sounds like bash and dash both close a file descriptor if you redirect it to &quot;&amp;-&quot;. So this wrapper might suffice (but you&#39;d have to ensure all supported shells work this way too, or you&#39;d again limit portability):</p><div class="source-code"><div class="toolbar"><span class="name">cloexec.sh</span><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="p">#!/bin/sh</span>
<span class="number">  2</span>
<span class="number">  3</span><span class="k1">if</span> <span class="k2">[</span> $# <span class="k3">-</span>le <span class="n">1</span> <span class="k2">]</span><span class="k2">;</span> then
<span class="number">  4</span>    cat <span class="k3">&lt;</span><span class="k3">&lt;</span>EOF <span class="n">1</span><span class="k3">&gt;</span><span class="k3">&amp;</span><span class="n">2</span><span class="k2">;</span>
<span class="number">  5</span>Usage: $<span class="n">0</span> FD COMMAND <span class="k2">[</span>ARG...<span class="k2">]</span>
<span class="number">  6</span>
<span class="number">  7</span>FD should be an integer file descriptor. FD will be closed immediately.
<span class="number">  8</span>
<span class="number">  9</span>Command will then be executed, receiving ARG... arguments.
<span class="number"> 10</span>EOF
<span class="number"> 11</span>    <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a> <span class="n">1</span><span class="k2">;</span>
<span class="number"> 12</span>fi<span class="k2">;</span>
<span class="number"> 13</span>
<span class="number"> 14</span>eval <span class="s">"$1&gt;&amp;-"</span> <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a> $?<span class="k2">;</span>
<span class="number"> 15</span>shift <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_298.html" target="_blank">exit</a> $?<span class="k2">;</span>
<span class="number"> 16</span><span class="s">"$@"</span><span class="k2">;</span>
</div></div><p>

That&#39;s in theory... In practice, this doesn&#39;t seem to work. <img src="http://www.allegro.cc/forums/smileys/undecided.gif" alt=":-/" /> Writing an equivalent C program that goes along with your program might be more portable anyway... But then that would probably have to reimplement <tt>popen</tt> to achieve this portably so probably the answer is just don&#39;t use popen if portability matters and this leaked file descriptor is significant.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Mon, 27 Mar 2017 20:42:35 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>In your case I would tend to use curl API directly in the code, which would avoid the command length problem, shell invocation &amp; stuff.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (GullRaDriel)</author>
		<pubDate>Mon, 27 Mar 2017 22:05:08 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I was hinted in another forum that cURL has something like multi interface: <a href="https://curl.haxx.se/libcurl/c/libcurl-multi.html">https://curl.haxx.se/libcurl/c/libcurl-multi.html</a></p><p>While this could probably allow me to make very fast HTTP requests straight from my main program in a non-blocking manner without using fork, it certainly would have a learning curve. So far I have only used simple curl requests API in my practice. This multi interface definitely looks promising but since I need to get this done already I wouldn&#39;t like to spend more time researching completely new possibilities to solve the matter. In fact, yesterday I made some pretty good progress with the initial approach. Below is the code that falls back to named pipes if the command line would be too long.</p><div class="source-code"><div class="toolbar"><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">   1</span><span class="k1">void</span> TREASURER::bitcoin_rpc<span class="k2">(</span><span class="k1">const</span> <span class="k1">char</span> <span class="k3">*</span>method, <span class="k1">const</span> nlohmann::json<span class="k3">*</span> params<span class="k2">)</span> <span class="k2">{</span>
<span class="number">   2</span>    <span class="c">/*</span>
<span class="number">   3</span><span class="c">     *  Instead of making a blocking cURL request here we are spawning a child</span>
<span class="number">   4</span><span class="c">     *  process with popen so that we can carry on with the main program while</span>
<span class="number">   5</span><span class="c">     *  the request is being executed. When the child process finishes it will</span>
<span class="number">   6</span><span class="c">     *  connect back to the main server providing us the response from Bitcoin RPC.</span>
<span class="number">   7</span><span class="c">     *  This clever trick achieves asynchronous HTTP requests without using threads</span>
<span class="number">   8</span><span class="c">     *  in our main process.</span>
<span class="number">   9</span><span class="c">     */</span>
<span class="number">  10</span>    <span class="k1">if</span> <span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> nullptr<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  11</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute Bitcoin RPC '%s': cookie not found."</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number">  12</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number">  13</span>    <span class="k2">}</span>
<span class="number">  14</span>
<span class="number">  15</span>    nlohmann::json json<span class="k2">;</span>
<span class="number">  16</span>    json<span class="k2">[</span><span class="s">"jsonrpc"</span><span class="k2">]</span> <span class="k3">=</span> <span class="s">"1.0"</span><span class="k2">;</span>
<span class="number">  17</span>    json<span class="k2">[</span><span class="s">"id"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number">  18</span>    json<span class="k2">[</span><span class="s">"method"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number">  19</span>    <span class="k1">if</span> <span class="k2">(</span>params<span class="k2">)</span> json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> <span class="k3">*</span>params<span class="k2">;</span>
<span class="number">  20</span>    <span class="k1">else</span>        json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> nlohmann::json::array<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  21</span>    <span class="c">//std::cout &lt;&lt; json.dump(4) &lt;&lt; std::endl;</span>
<span class="number">  22</span>
<span class="number">  23</span>    <span class="k1">long</span> arg_max <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_801.html" target="_blank">sysconf</a><span class="k2">(</span>_SC_ARG_MAX<span class="k2">)</span><span class="k2">;</span>
<span class="number">  24</span>    <span class="k1">size_t</span> max_len <span class="k3">=</span> arg_max<span class="k3">/</span><span class="n">16</span> <span class="k3">-</span> <span class="n">1</span><span class="k2">;</span>
<span class="number">  25</span>
<span class="number">  26</span>    std::string cfg<span class="k2">;</span>
<span class="number">  27</span>    cfg.append<span class="k2">(</span><span class="s">"--url http://127.0.0.1:8332/\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  28</span>    cfg.append<span class="k2">(</span><span class="s">"--max-time 10\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  29</span>    cfg.append<span class="k2">(</span><span class="s">"-u "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  30</span>    cfg.append<span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  31</span>    cfg.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\n'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  32</span>    cfg.append<span class="k2">(</span><span class="s">"-H \"content-type: text/plain;\"\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  33</span>    cfg.append<span class="k2">(</span><span class="s">"--data-binary @-\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  34</span>    cfg.append<span class="k2">(</span>json.dump<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  35</span>
<span class="number">  36</span>    std::string hex<span class="k2">;</span>
<span class="number">  37</span>    str2hex<span class="k2">(</span>cfg.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="k3">&amp;</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number">  38</span>
<span class="number">  39</span>    std::string command <span class="k3">=</span> <span class="s">"{ { printf 'su\\nsend "</span><span class="k2">;</span>
<span class="number">  40</span>    command.append<span class="k2">(</span>std::to_string<span class="k2">(</span>id<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  41</span>    command.append<span class="k2">(</span><span class="s">" '"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  42</span>    command.append<span class="k2">(</span><span class="s">" ; printf '%s' '"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  43</span>    command.append<span class="k2">(</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number">  44</span>    command.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\''</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  45</span>    command.append<span class="k2">(</span><span class="s">" | xxd -p -r"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  46</span>    command.append<span class="k2">(</span><span class="s">" | curl -s --config -"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  47</span>    command.append<span class="k2">(</span><span class="s">" ; printf '\\nexit\\nexit\\n' ; }"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  48</span>    command.append<span class="k2">(</span><span class="s">" | netcat -q -1 127.0.0.1 "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  49</span>    command.append<span class="k2">(</span>manager-&gt;get_tcp_port<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  50</span>    command.append<span class="k2">(</span><span class="s">" ; } &amp;"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  51</span>
<span class="number">  52</span>    manager-&gt;vlog<span class="k2">(</span><span class="s">"Bitcoin RPC ---&gt; %s"</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number">  53</span>    <span class="k1">if</span> <span class="k2">(</span>command.length<span class="k2">(</span><span class="k2">)</span> <span class="k3">&gt;</span> max_len<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  54</span>        <span class="k1">char</span> salt<span class="k2">[</span><span class="n">16</span><span class="k2">]</span><span class="k2">;</span>
<span class="number">  55</span>        generate_salt<span class="k2">(</span>salt, <span class="k1">sizeof</span><span class="k2">(</span>salt<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  56</span>        std::string fifo <span class="k3">=</span> <span class="s">"./data/tmp/"</span><span class="k2">;</span>
<span class="number">  57</span>        fifo.append<span class="k2">(</span>salt<span class="k2">)</span><span class="k2">;</span>
<span class="number">  58</span>        fifo.append<span class="k2">(</span><span class="s">".fifo"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  59</span>
<span class="number">  60</span>        <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a> <span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_571.html" target="_blank">mkfifo</a><span class="k2">(</span>fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="n">0600</span><span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  61</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"%s: mkfifo %s: %s"</span>, __FUNCTION__, fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  62</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number">  63</span>        <span class="k2">}</span>
<span class="number">  64</span>
<span class="number">  65</span>        command <span class="k3">=</span> <span class="s">"{ { printf 'su\\nsend "</span><span class="k2">;</span>
<span class="number">  66</span>        command.append<span class="k2">(</span>std::to_string<span class="k2">(</span>id<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  67</span>        command.append<span class="k2">(</span><span class="s">" '"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  68</span>        command.append<span class="k2">(</span><span class="s">" ; cat "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  69</span>        command.append<span class="k2">(</span>fifo<span class="k2">)</span><span class="k2">;</span>
<span class="number">  70</span>        command.append<span class="k2">(</span><span class="s">" | curl -s --config -"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  71</span>        command.append<span class="k2">(</span><span class="s">" ; printf '\\nexit\\nexit\\n' ; }"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  72</span>        command.append<span class="k2">(</span><span class="s">" | netcat -q -1 127.0.0.1 "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  73</span>        command.append<span class="k2">(</span>manager-&gt;get_tcp_port<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  74</span>        command.append<span class="k2">(</span><span class="s">" ; rm -f "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  75</span>        command.append<span class="k2">(</span>fifo<span class="k2">)</span><span class="k2">;</span>
<span class="number">  76</span>        command.append<span class="k2">(</span><span class="s">" ; } &amp;"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  77</span>
<span class="number">  78</span>        FILE <span class="k3">*</span>fp <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span>command.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="s">"r"</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Open the command for reading.</span>
<span class="number">  79</span>        <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>fp<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  80</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute '%s'.\n"</span>, command.c_str<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  81</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number">  82</span>        <span class="k2">}</span>
<span class="number">  83</span>        <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>fp<span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  84</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"%s: pclose: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  85</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number">  86</span>        <span class="k2">}</span>
<span class="number">  87</span>
<span class="number">  88</span>        <span class="k2">{</span>
<span class="number">  89</span>            signals.block<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  90</span>            <span class="k1">int</span> fd <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_600.html" target="_blank">open</a><span class="k2">(</span>fifo.c_str<span class="k2">(</span><span class="k2">)</span>, O_WRONLY<span class="k2">)</span><span class="k2">;</span>
<span class="number">  91</span>
<span class="number">  92</span>            <span class="k1">if</span> <span class="k2">(</span>fd <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  93</span>                manager-&gt;bug<span class="k2">(</span><span class="s">"%s: open %s: %s"</span>, __FUNCTION__, fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  94</span>                signals.unblock<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  95</span>                <span class="k1">return</span><span class="k2">;</span>
<span class="number">  96</span>            <span class="k2">}</span>
<span class="number">  97</span>
<span class="number">  98</span>            ssize_t written <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_866.html" target="_blank">write</a><span class="k2">(</span>fd, cfg.c_str<span class="k2">(</span><span class="k2">)</span>, cfg.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  99</span>            <span class="k1">if</span> <span class="k2">(</span>written <span class="k3">!</span><span class="k3">=</span> <span class="k2">(</span>ssize_t<span class="k2">)</span> cfg.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 100</span>                <span class="k1">if</span> <span class="k2">(</span>written <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: write: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 101</span>                <span class="k1">else</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: write: wrong number of bytes written"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 102</span>            <span class="k2">}</span>
<span class="number"> 103</span>            <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a> <span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>fd<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: close: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 104</span>            signals.unblock<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 105</span>        <span class="k2">}</span>
<span class="number"> 106</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 107</span>    <span class="k2">}</span>
<span class="number"> 108</span>
<span class="number"> 109</span>    FILE <span class="k3">*</span>fp <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span>command.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="s">"r"</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Open the command for reading.</span>
<span class="number"> 110</span>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>fp<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 111</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute '%s'.\n"</span>, command.c_str<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 112</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 113</span>    <span class="k2">}</span>
<span class="number"> 114</span>    <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>fp<span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 115</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"%s: pclose: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 116</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 117</span>    <span class="k2">}</span>
<span class="number"> 118</span><span class="k2">}</span>
</div></div><p>

It works well but there are a couple enhancements that I&#39;d really need. Firstly there are these 2 lines:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">long</span> arg_max <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_801.html" target="_blank">sysconf</a><span class="k2">(</span>_SC_ARG_MAX<span class="k2">)</span><span class="k2">;</span>
<span class="k1">size_t</span> max_len <span class="k3">=</span> arg_max<span class="k3">/</span><span class="n">16</span> <span class="k3">-</span> <span class="n">1</span><span class="k2">;</span>
</pre></div></div><p>
With trial and error I found out that maximum command length is ARG_MAX/16 - 1. Could there be any portable way of determining that limit? I&#39;m afraid ARG_MAX/16 could be either a coincidence or specific to my particular development platform.</p><p>I will also probably have to add some CLOEXEC flags here and there.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Tue, 28 Mar 2017 12:21:18 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>You should consider to put curl calls in a fork because depending the version it&#39;s known to leak, so if it happens to you there is already a solution.</p><p>The command line max size depends of the host.</p><p>For the command max size here is what I got on linux:
</p><div class="source-code snippet"><div class="inner"><pre>gull@Althea:~$ xargs <span class="k3">-</span><span class="k3">-</span>show-limits
Vos variables d<span class="s">'environnement occupent 2625 octets</span>
<span class="s">Limite supérieure POSIX de longueur d'</span>argument <span class="k2">(</span>sur ce systme<span class="k2">)</span><span class="k2">:</span> <span class="n">2092479</span>
Plus petite limite haute POSIX de longueur d<span class="s">'argument autorisée (tous systèmes) : 4096</span>
<span class="s">Longueur maximale de la commande qui pourrait être utilisée : 2089854</span>
<span class="s">Taille du tampon de commande actuellement utilisé : 131072</span>
<span class="s">Parallélisation maximum (--max-procs ne peut pas être plus grand): 2147483647</span>
<span class="s"></span>
<span class="s">L'</span>excution de xargs va continuer maintenant et tenter de lire les donnes en entre et excuter les commandes<span class="k2">;</span> si vous ne le voulez pas, pressez <span class="k3">&lt;</span>Ctrl-D&gt; <span class="k2">(</span>EOF<span class="k2">)</span>.
Attention<span class="k2">:</span> echo va s<span class="s">'exécuter au moins une fois. Si vous ne le voulez pas, pressez les touches d'</span>interruption.
</pre></div></div><p>
That should work for linux systems. It shows that I can have a maximum 2MB command line.</p><p>For windows: <a href="https://support.microsoft.com/fr-fr/help/830473/command-prompt-cmd.-exe-command-line-string-limitation">https://support.microsoft.com/fr-fr/help/830473/command-prompt-cmd.-exe-command-line-string-limitation</a></p><p>You may switch to english to have a better understanding of what it says.</p><p>Edited.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (GullRaDriel)</author>
		<pubDate>Wed, 29 Mar 2017 00:11:20 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Any idea how to programmatically calculate the value shown on this line:<br />Taille du tampon de commande actuellement utilisé : 131072</p><p>Or perhaps you know some guaranteed minimum command line buffer size and how to get its value? It seems to me that 4096 is the guaranteed minimum argument length but I am not 100% sure about that.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Wed, 29 Mar 2017 17:33:55 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>For my system: the currently allocated buffer is 131072 of 2 usable MB.</p><p>That link may got what you want:<br /><a href="https://www.in-ulm.de/~mascheck/various/argmax/">https://www.in-ulm.de/~mascheck/various/argmax/</a>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (GullRaDriel)</author>
		<pubDate>Wed, 29 Mar 2017 22:57:24 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The xargs tool is free software. You can go look up how it does it. <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Wed, 29 Mar 2017 23:52:31 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>@bamccaig</p><p>I did look at xargs source. <img src="http://www.allegro.cc/forums/smileys/cheesy.gif" alt=":D" /> And it was ugly. I mean there were quite a few checks to determine that length and in some cases I believe the fallback was just to gradually increase the length of a string and feed it to command line interpreter until it fails. I believe I did see some reference to a guaranteed minimum buffer size for the command line and it was 4096. So I am now simply using that number in my code because in my case it is enough in 99% of cases. And those 1% of cases when 4096 is not enough then even 131072 would not be enough so I&#39;m using named pipes fallback anyway.</p><p>Here&#39;s the new version of my function. I had to get rid of curly brackets between printf commands because turned out that when curl made requests to remote hosts rather than to localhost then the delay between printf and curl subsequent commands were so big that netcat registered an EOF from the first call to printf, after which curl closed with error &quot;23 failed writing body&quot;. This problem was not manifesting when I tested locally. A fixed version uses xargs to turn the stdin into a command line parameter of another command.</p><div class="source-code"><div class="toolbar"><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">   1</span><span class="k1">void</span> TREASURER::bitcoin_rpc<span class="k2">(</span><span class="k1">const</span> <span class="k1">char</span> <span class="k3">*</span>method, <span class="k1">const</span> nlohmann::json<span class="k3">*</span> params<span class="k2">)</span> <span class="k2">{</span>
<span class="number">   2</span>    <span class="c">/*</span>
<span class="number">   3</span><span class="c">     *  Instead of making a blocking cURL request here we are spawning a child</span>
<span class="number">   4</span><span class="c">     *  process with popen so that we can carry on with the main program while</span>
<span class="number">   5</span><span class="c">     *  the request is being executed. When the child process finishes it will</span>
<span class="number">   6</span><span class="c">     *  connect back to the main server providing us the response from Bitcoin RPC.</span>
<span class="number">   7</span><span class="c">     *  This clever trick achieves asynchronous HTTP requests without using threads</span>
<span class="number">   8</span><span class="c">     *  in our main process.</span>
<span class="number">   9</span><span class="c">     */</span>
<span class="number">  10</span>    <span class="k1">if</span> <span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> nullptr<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  11</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute Bitcoin RPC '%s': cookie not found."</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number">  12</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number">  13</span>    <span class="k2">}</span>
<span class="number">  14</span>
<span class="number">  15</span>    <span class="k1">if</span> <span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"wallet-host"</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> nullptr<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  16</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute Bitcoin RPC '%s': wallet host not set."</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number">  17</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number">  18</span>    <span class="k2">}</span>
<span class="number">  19</span>
<span class="number">  20</span>    <span class="k1">if</span> <span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"wallet-port"</span><span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> nullptr<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  21</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute Bitcoin RPC '%s': wallet port not set."</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number">  22</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number">  23</span>    <span class="k2">}</span>
<span class="number">  24</span>
<span class="number">  25</span>    nlohmann::json json<span class="k2">;</span>
<span class="number">  26</span>    json<span class="k2">[</span><span class="s">"jsonrpc"</span><span class="k2">]</span> <span class="k3">=</span> <span class="s">"1.0"</span><span class="k2">;</span>
<span class="number">  27</span>    json<span class="k2">[</span><span class="s">"id"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number">  28</span>    json<span class="k2">[</span><span class="s">"method"</span><span class="k2">]</span> <span class="k3">=</span> method<span class="k2">;</span>
<span class="number">  29</span>    <span class="k1">if</span> <span class="k2">(</span>params<span class="k2">)</span> json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> <span class="k3">*</span>params<span class="k2">;</span>
<span class="number">  30</span>    <span class="k1">else</span>        json<span class="k2">[</span><span class="s">"params"</span><span class="k2">]</span> <span class="k3">=</span> nlohmann::json::array<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  31</span>    <span class="c">//std::cout &lt;&lt; json.dump(4) &lt;&lt; std::endl;</span>
<span class="number">  32</span>
<span class="number">  33</span>    <span class="k1">size_t</span> max_len <span class="k3">=</span> <span class="n">4096</span> <span class="k3">-</span> <span class="n">1</span><span class="k2">;</span> <span class="c">// Maximum command line length.</span>
<span class="number">  34</span>
<span class="number">  35</span>    std::string request <span class="k3">=</span> json.dump<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  36</span>    std::string cfg<span class="k2">;</span>
<span class="number">  37</span>    cfg.append<span class="k2">(</span><span class="s">"--url http://"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  38</span>    cfg.append<span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"wallet-host"</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  39</span>    cfg.append<span class="k2">(</span><span class="n">1</span>, <span class="s">':'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  40</span>    cfg.append<span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"wallet-port"</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  41</span>    cfg.append<span class="k2">(</span><span class="s">"/\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  42</span>    cfg.append<span class="k2">(</span><span class="s">"--max-time 10\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  43</span>    cfg.append<span class="k2">(</span><span class="s">"-u "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  44</span>    cfg.append<span class="k2">(</span>manager-&gt;get_global<span class="k2">(</span><span class="s">"auth-cookie"</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  45</span>    cfg.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\n'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  46</span>    cfg.append<span class="k2">(</span><span class="s">"-H \"content-type: text/plain;\"\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  47</span>    cfg.append<span class="k2">(</span><span class="s">"--data-binary @-\n"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  48</span>    cfg.append<span class="k2">(</span>request<span class="k2">)</span><span class="k2">;</span>
<span class="number">  49</span>
<span class="number">  50</span>    std::string hex<span class="k2">;</span>
<span class="number">  51</span>    str2hex<span class="k2">(</span>cfg.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="k3">&amp;</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number">  52</span>
<span class="number">  53</span>    std::string command <span class="k3">=</span> <span class="s">"printf \"%s\" \""</span><span class="k2">;</span>
<span class="number">  54</span>    command.append<span class="k2">(</span>hex<span class="k2">)</span><span class="k2">;</span>
<span class="number">  55</span>    command.append<span class="k2">(</span><span class="n">1</span>, <span class="s">'\"'</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  56</span>    command.append<span class="k2">(</span><span class="s">" | xxd -p -r "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  57</span>    command.append<span class="k2">(</span><span class="s">" | curl -s --config - "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  58</span>    command.append<span class="k2">(</span><span class="s">" | xargs -0 printf 'su\\nsend "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  59</span>    command.append<span class="k2">(</span>std::to_string<span class="k2">(</span>id<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  60</span>    command.append<span class="k2">(</span><span class="s">" %s\\nexit\\nexit\\n'"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  61</span>    command.append<span class="k2">(</span><span class="s">" | netcat -q -1 127.0.0.1 "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  62</span>    command.append<span class="k2">(</span>manager-&gt;get_tcp_port<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  63</span>    command.append<span class="k2">(</span><span class="s">" &amp;"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  64</span>
<span class="number">  65</span>
<span class="number">  66</span>    <span class="k1">if</span> <span class="k2">(</span>command.length<span class="k2">(</span><span class="k2">)</span> <span class="k3">&gt;</span> max_len<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  67</span>        manager-&gt;log<span class="k2">(</span><span class="s">"Bitcoin RPC ---&gt; %s (%lu bytes)"</span>, method, request.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  68</span>        <span class="k1">char</span> salt<span class="k2">[</span><span class="n">16</span><span class="k2">]</span><span class="k2">;</span>
<span class="number">  69</span>        generate_salt<span class="k2">(</span>salt, <span class="k1">sizeof</span><span class="k2">(</span>salt<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  70</span>        std::string fifo <span class="k3">=</span> options.datadir<span class="k2">;</span>
<span class="number">  71</span>        fifo.append<span class="k2">(</span><span class="s">"/tmp/"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  72</span>        fifo.append<span class="k2">(</span>salt<span class="k2">)</span><span class="k2">;</span>
<span class="number">  73</span>        fifo.append<span class="k2">(</span><span class="s">".fifo"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  74</span>
<span class="number">  75</span>        <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a> <span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_571.html" target="_blank">mkfifo</a><span class="k2">(</span>fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="n">0600</span><span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  76</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"%s: mkfifo %s: %s"</span>, __FUNCTION__, fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  77</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number">  78</span>        <span class="k2">}</span>
<span class="number">  79</span>
<span class="number">  80</span>        command <span class="k3">=</span> <span class="s">"{ { printf 'su\\nsend "</span><span class="k2">;</span>
<span class="number">  81</span>        command.append<span class="k2">(</span>std::to_string<span class="k2">(</span>id<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  82</span>        command.append<span class="k2">(</span><span class="s">" '"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  83</span>        command.append<span class="k2">(</span><span class="s">" ; cat "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  84</span>        command.append<span class="k2">(</span>fifo<span class="k2">)</span><span class="k2">;</span>
<span class="number">  85</span>        command.append<span class="k2">(</span><span class="s">" | curl -s --config -"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  86</span>        command.append<span class="k2">(</span><span class="s">" ; printf '\\nexit\\nexit\\n' ; }"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  87</span>        command.append<span class="k2">(</span><span class="s">" | netcat -q -1 127.0.0.1 "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  88</span>        command.append<span class="k2">(</span>manager-&gt;get_tcp_port<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  89</span>        command.append<span class="k2">(</span><span class="s">" ; rm -f "</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  90</span>        command.append<span class="k2">(</span>fifo<span class="k2">)</span><span class="k2">;</span>
<span class="number">  91</span>        command.append<span class="k2">(</span><span class="s">" ; } &amp;"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  92</span>
<span class="number">  93</span>        FILE <span class="k3">*</span>fp <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span>command.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="s">"re"</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Open the command for reading.</span>
<span class="number">  94</span>        <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>fp<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  95</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute '%s'.\n"</span>, command.c_str<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number">  96</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number">  97</span>        <span class="k2">}</span>
<span class="number">  98</span>        <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>fp<span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number">  99</span>            manager-&gt;bug<span class="k2">(</span><span class="s">"%s: pclose: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 100</span>            <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 101</span>        <span class="k2">}</span>
<span class="number"> 102</span>
<span class="number"> 103</span>        <span class="k2">{</span>
<span class="number"> 104</span>            signals.block<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 105</span>            <span class="k1">int</span> fd <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_600.html" target="_blank">open</a><span class="k2">(</span>fifo.c_str<span class="k2">(</span><span class="k2">)</span>, O_CLOEXEC<span class="k3">|</span>O_WRONLY<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 106</span>
<span class="number"> 107</span>            <span class="k1">if</span> <span class="k2">(</span>fd <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 108</span>                manager-&gt;bug<span class="k2">(</span><span class="s">"%s: open %s: %s"</span>, __FUNCTION__, fifo.c_str<span class="k2">(</span><span class="k2">)</span>, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 109</span>                signals.unblock<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 110</span>                <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 111</span>            <span class="k2">}</span>
<span class="number"> 112</span>
<span class="number"> 113</span>            ssize_t written <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_866.html" target="_blank">write</a><span class="k2">(</span>fd, cfg.c_str<span class="k2">(</span><span class="k2">)</span>, cfg.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 114</span>            <span class="k1">if</span> <span class="k2">(</span>written <span class="k3">!</span><span class="k3">=</span> <span class="k2">(</span>ssize_t<span class="k2">)</span> cfg.size<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 115</span>                <span class="k1">if</span> <span class="k2">(</span>written <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: write: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 116</span>                <span class="k1">else</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: write: wrong number of bytes written"</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 117</span>            <span class="k2">}</span>
<span class="number"> 118</span>            <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a> <span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_104.html" target="_blank">close</a><span class="k2">(</span>fd<span class="k2">)</span> <span class="k3">!</span><span class="k3">=</span> <span class="n">0</span><span class="k2">)</span> manager-&gt;bug<span class="k2">(</span><span class="s">"%s: close: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 119</span>            signals.unblock<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 120</span>        <span class="k2">}</span>
<span class="number"> 121</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 122</span>    <span class="k2">}</span>
<span class="number"> 123</span>    <span class="k1">else</span> manager-&gt;vlog<span class="k2">(</span><span class="s">"Bitcoin RPC ---&gt; %s"</span>, method<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 124</span>
<span class="number"> 125</span>    FILE <span class="k3">*</span>fp <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_617.html" target="_blank">popen</a><span class="k2">(</span>command.c_str<span class="k2">(</span><span class="k2">)</span>, <span class="s">"re"</span><span class="k2">)</span><span class="k2">;</span> <span class="c">// Open the command for reading.</span>
<span class="number"> 126</span>    <span class="k1">if</span> <span class="k2">(</span><span class="k3">!</span>fp<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 127</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"Unable to execute '%s'.\n"</span>, command.c_str<span class="k2">(</span><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 128</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 129</span>    <span class="k2">}</span>
<span class="number"> 130</span>    <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_614.html" target="_blank">pclose</a><span class="k2">(</span>fp<span class="k2">)</span> <span class="k3">=</span><span class="k3">=</span> <span class="k3">-</span><span class="n">1</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 131</span>        manager-&gt;bug<span class="k2">(</span><span class="s">"%s: pclose: %s"</span>, __FUNCTION__, <a href="http://www.delorie.com/djgpp/doc/libc/libc_759.html" target="_blank">strerror</a><span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_293.html" target="_blank">errno</a><span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 132</span>        <span class="k1">return</span><span class="k2">;</span>
<span class="number"> 133</span>    <span class="k2">}</span>
<span class="number"> 134</span><span class="k2">}</span>
</div></div><p>

edit:<br />Damn, I almost forgot that the fallback also has to get rid off semicolons and printf to add a prefix and suffix for the string returned by curl before feeding it to netcat. And in case of non-fallback if the string returned by curl is too long then xargs will fail also.</p><p>Any ideas how to add a prefix and suffix to the string that we get from stdin before directing it to stdout?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Thu, 30 Mar 2017 11:28:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I don&#39;t quite get the problem with your last question.</p><p>1) You get a sting from stdin which you store in string_in<br />2) You allocate a new empty string newstring<br />3) append prefix to newstring<br />4) append string_in to newstring<br />5) append suffix to newstring<br />6) cout newstring ?</p><p>or shorter:</p><p>1)Prepare a new empty string <br />2)append prefix<br />3)append stdin <br />4)append suffix <br />5)cout newstring
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (GullRaDriel)</author>
		<pubDate>Fri, 31 Mar 2017 14:38:22 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I just made some more progress.</p><p>Here is my old code that had a weird behavior. My program was never reported back from netcat when I spawned the curl with popen like that:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k2">{</span> <span class="k2">{</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'73750a6c6f6720776f6f7420'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'2d2d75726c2068747470733a2f2f626974636f696e666565732e32312e636f2f6170692f76312f666565732f7265636f6d6d656e6465640a2d2d6d61782d74696d652031300a'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k3">|</span> curl <span class="k3">-</span>N <span class="k3">-</span>s <span class="k3">-</span><span class="k3">-</span>config <span class="k3">-</span> <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'0a657869740a657869740a'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k2">;</span> <span class="k2">}</span> <span class="k3">|</span> netcat <span class="k3">-</span>I <span class="n">23</span> <span class="k3">-</span>O <span class="n">23</span> <span class="k3">-</span>q <span class="n">60</span> <span class="k3">-</span>w <span class="n">60</span> <span class="n">127</span>.<span class="n">0</span>.<span class="n">0</span>.<span class="n">1</span> <span class="n">4000</span> <span class="k2">;</span> rm <span class="k3">-</span>f .<span class="k3">/</span>data<span class="k3">/</span>tmp<span class="k3">/</span>fa37JncCHryDsbz.fifo <span class="k2">;</span> <span class="k2">}</span> <span class="k3">&amp;</span>
</pre></div></div><p>

I was unable to figure out why the shell started from popen did not finish properly. I still don&#39;t quite know why the previous code does not work but after adding unbuffer -p in front of the netcat command everything started to work. It is even more strange that stdbuf -i0 -o0 -e0 in front of netcat did not make any difference. So the unbuffer command does some magic that made my program work.
</p><div class="source-code snippet"><div class="inner"><pre><span class="k2">{</span> <span class="k2">{</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'73750a6c6f6720776f6f7420'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'2d2d75726c2068747470733a2f2f626974636f696e666565732e32312e636f2f6170692f76312f666565732f7265636f6d6d656e6465640a2d2d6d61782d74696d652031300a'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k3">|</span> curl <span class="k3">-</span>N <span class="k3">-</span>s <span class="k3">-</span><span class="k3">-</span>config <span class="k3">-</span> <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s'</span> <span class="s">'0a657869740a657869740a'</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r <span class="k2">;</span> <span class="k2">}</span> <span class="k3">|</span> unbuffer <span class="k3">-</span>p netcat <span class="k3">-</span>I <span class="n">23</span> <span class="k3">-</span>O <span class="n">23</span> <span class="k3">-</span>q <span class="n">60</span> <span class="k3">-</span>w <span class="n">60</span> <span class="n">127</span>.<span class="n">0</span>.<span class="n">0</span>.<span class="n">1</span> <span class="n">4000</span> <span class="k2">;</span> rm <span class="k3">-</span>f .<span class="k3">/</span>data<span class="k3">/</span>tmp<span class="k3">/</span>fa37JncCHryDsbz.fifo <span class="k2">;</span> <span class="k2">}</span> <span class="k3">&amp;</span>
</pre></div></div><p>

This stuff is quite hard to debug because when I start those commands from my terminal window they both finish nicely. The first version of the command is only malfunctioning when it is started with popen from the very process that is supposed to receive the curl response via netcat in the end.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Fri, 31 Mar 2017 16:21:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The issue then is that somehow buffered IO was causing something to fail?</p><p>Site note: String manipulation is going to require &quot;slow&quot; memory allocations that likely will be immediately thrown out after. Avoid needless string memory options using a std::stringstream to build the final string or writing directly to the output stream instead of concatenating into a string first.</p><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/616818/1029439#target">GullRaDriel</a> said:</div><div class="quote"><p>1) You get a sting from stdin which you store in string_in<br />2) cout prefix<br />3) cout string_in<br />4) cout suffix ?</p></div></div><p>

FTFY. Or if you need the whole string, use the stringstream as above. I imagine it&#39;s more efficient (modern libraries usually have a &quot;StringBuilder&quot; or equivalent that does this same thing to avoid constantly reallocating string objects...at least in C++ the same buffer <i>might</i> just be getting extended without copying).</p><p>While I&#39;m nitpicking, <tt>printf &#39;%s&#39; &#39;x&#39;</tt> is the same as <tt>echo -n &#39;x&#39;</tt> (but maybe that&#39;s not as portable?).</p><p>While I&#39;m on the subject of portability, my netcat in Linux doesn&#39;t have -I or -O options... <img src="http://www.allegro.cc/forums/smileys/undecided.gif" alt=":-/" /> Are you sure <i>that&#39;s</i> portable?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Fri, 31 Mar 2017 19:38:11 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Well those -I -O options didn&#39;t do anything good anyway. So I have already dropped these. Everything would have been perfect if unbuffered would have worked for large responses too. This is getting sad already <img src="http://www.allegro.cc/forums/smileys/cheesy.gif" alt=":D" /> turns out the unbuffer function gave me only the first n bytes of the curl response so it is of no use. I am running out of ideas.</p><p>edit:<br />This is becoming ridiculous. I want to add just a string prefix and suffix to whatever curl writes to its stdout before feeding it to netcat. And it does not work, I&#39;ve tried hundres of combinations, using stdbuf and unbuffer, some hacks with variables. Unbuffer almost worked but it started failing on larger curl responses.</p><p>About std::strings being slow, I&#39;m not buying it. Let&#39;s say I reserve 1000 bytes for the string right away and then append to it, no way it would be slow.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Fri, 31 Mar 2017 19:54:31 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Maybe it would help to debug to write each stdout to files so that you can inspect the results at each stage? Instead of piping, write to a file, and then substitute that file for the stdin of the next process.</p><p><b>Append:</b></p><p>Agreed, if you reserve space for the string ahead of time you can avoid the overhead. That is, if you know a reasonable size to use. If it can vary a lot, you could be wasting lots of memory or still run into reallocation overhead.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (bamccaig)</author>
		<pubDate>Fri, 31 Mar 2017 20:10:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yes I tested with files and it worked well. I did not test file based logic with large curl responses though. Perhaps I could utilize named pipes somehow, if I&#39;m using them anyway in case of requests that have large bodies.</p><p><b>Append</b><br />I just made humongous progress solving this issue. I suspect there is a bug in the popen system call or perhaps in Linux kernel. Turns out that if I called popen in write mode instead of read mode then everything started working as expected.</p><p>More about it here:<br /><a href="https://forums.linuxmint.com/viewtopic.php?f=47&amp;t=242879&amp;p=1298492#p1298492">https://forums.linuxmint.com/viewtopic.php?f=47&amp;t=242879&amp;p=1298492#p1298492</a></p><p><b>Append 2</b><br />Holy mother of god! I just tested and turns out that popen in read mode can also be fixed with a really simple trick. Here&#39;s the fixed command line:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k2">{</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s\n%s\n%s'</span> <span class="s">'su'</span> <span class="s">'log start'</span> <span class="s">'log '</span> <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">"%s"</span> <span class="s">"2d2d75726c2068747470733a2f2f626c6f636b636861696e2e696e666f2f726177626c6f636b2f3237373737373f666f726d61743d6865780a2d2d6d61782d74696d652031300a2d482022636f6e74656e742d747970653a20746578742f706c61696e3b220a"</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r  <span class="k3">|</span> curl <span class="k3">-</span>s <span class="k3">-</span><span class="k3">-</span>config <span class="k3">-</span> <span class="k3">|</span> tail <span class="k3">-</span>c <span class="n">10</span>  <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'\nlog end\n%s\n%s\n'</span> <span class="s">'exit'</span> <span class="s">'exit'</span> <span class="k2">;</span> <span class="k2">}</span> <span class="k3">|</span> netcat <span class="k3">-</span>q <span class="n">10</span> <span class="k3">-</span>w <span class="n">10</span> <span class="n">127</span>.<span class="n">0</span>.<span class="n">0</span>.<span class="n">1</span> <span class="n">4000</span> <span class="k3">&gt;</span> <span class="k3">/</span>dev<span class="k3">/</span>null <span class="n">2</span><span class="k3">&gt;</span><span class="k3">/</span>dev<span class="k3">/</span>null <span class="k3">&amp;</span>
</pre></div></div><p>

And here&#39;s the malfunctioning one:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k2">{</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'%s\n%s\n%s'</span> <span class="s">'su'</span> <span class="s">'log start'</span> <span class="s">'log '</span> <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">"%s"</span> <span class="s">"2d2d75726c2068747470733a2f2f626c6f636b636861696e2e696e666f2f726177626c6f636b2f3237373737373f666f726d61743d6865780a2d2d6d61782d74696d652031300a2d482022636f6e74656e742d747970653a20746578742f706c61696e3b220a"</span> <span class="k3">|</span> xxd <span class="k3">-</span>p <span class="k3">-</span>r  <span class="k3">|</span> curl <span class="k3">-</span>s <span class="k3">-</span><span class="k3">-</span>config <span class="k3">-</span> <span class="k3">|</span> tail <span class="k3">-</span>c <span class="n">10</span>  <span class="k2">;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_624.html" target="_blank">printf</a> <span class="s">'\nlog end\n%s\n%s\n'</span> <span class="s">'exit'</span> <span class="s">'exit'</span> <span class="k2">;</span> <span class="k2">}</span> <span class="k3">|</span> netcat <span class="k3">-</span>q <span class="n">10</span> <span class="k3">-</span>w <span class="n">10</span> <span class="n">127</span>.<span class="n">0</span>.<span class="n">0</span>.<span class="n">1</span> <span class="n">4000</span> <span class="k3">&gt;</span> <span class="k3">&amp;</span>
</pre></div></div><p>

As you can see redirection of stdout and stderr to /dev/null made it work?! <img src="http://www.allegro.cc/forums/smileys/grin.gif" alt=";D" /> <img src="http://www.allegro.cc/forums/smileys/huh.gif" alt="???" />
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Hyena_)</author>
		<pubDate>Fri, 31 Mar 2017 20:14:16 +0000</pubDate>
	</item>
</rss>
