How to use a wildcard expression within system() - c++

The following command runs fine on my embedded Linux (Beaglebone Black):
echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots
But not when using this small C++ program:
#include <stdlib.h>
#include <string>
int main {
system(std::string("echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots").c_str());
return 0;
}
The problem involves the '?' question mark, that is used as a wildcard.
When the question mark, in the std::string that is passed to system(), is replaced with a normal character, the system() function evaluates the command perfect.
Solutions I've tried without success:
replace ? with \?
replace ? with *

Apart from your code not being compilable, this fails because system(3) runs sh, often a minimal shell provided by dash or busybox.
Meanwhile, your interactive login uses bash, ksh or some other more comfy shell.
dash and busybox sh do not do glob expansion on redirections, while bash and ksh do. Here's a demonstration of the behavior you want courtesy of bash:
$ touch file.txt
$ bash -c 'echo "bash contents" > *.txt'
$ cat file.txt
bash contents
Meanwhile, the problem you're having with e.g. dash:
$ dash -c 'echo "and now dash" > *.txt'
$ ls
*.txt file.txt
$ cat '*.txt' # Instead of expanding, the path was taken literally
and now dash
$ cat file.txt
bash contents
To fix this, you can (in order of preference)
Write your C program in C code instead of shell script
Call a better shell with execve.
Rewrite to not write to a glob, e.g. echo "stuff" | tee *.txt > /dev/null
Call a better shell with system, e.g. bash -c "echo stuff > *.txt"

NOTE: As πάντα ῥεῖ pointed out the system() command calls the shell which will usually do the expansion when presented with the correct wildcard: *. This answer is thereful more appropriate if you want the control to make each system() call separately or if the underlying shell is limited.
Original answer:
Perhaps you could use wordexp for this to construct your strings before you make the system() call:
#include <string>
#include <vector>
#include <iostream>
#include <wordexp.h>
std::vector<std::string> expand_env(const std::string& var, int flags = 0)
{
std::vector<std::string> vars;
wordexp_t p;
if(!wordexp(var.c_str(), &p, flags))
{
if(p.we_wordc)
for(char** exp = p.we_wordv; *exp; ++exp)
vars.push_back(exp[0]);
wordfree(&p);
}
return vars;
}
int main()
{
for(auto&& s: expand_env("$HOME/*")) // <= Note the wildcard '*'
std::cout << s << '\n';
}
In your specific case you could perhaps use something like this:
int main()
{
std::vector<std::string> devices = expand_env("/sys/devices/bone_capemgr.*/slots");
for(std::vector<std::string>::size_type i = 0; i < devices.size(); ++i)
system(("echo bone_pwm_P9_21 > " + devices[i]).c_str());
}

Related

passing input value from bash script to a c++ executable

I have a c++ code which requires an input value. I would like to have a bash script to run my c++ executable file automatically. My bash script is below:
#!/bin/bash
g++ freshness.cpp -g -o prob
for((i=0;i<30;i++))
{
./prob<$2 ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
}
./cal result.txt
rm result.txt
My main.cpp is below:
int main(int argc,char*argv[])
{
map<int, struct Router> nodes;
cout<<"creating routers..."<<endl;
Create_router(argv[1],nodes);
cout<<"creating topology..."<<endl;
LoadRouting(argv[2],nodes);
cout<<"simulating..."<<endl;
Simulate(argv[3],nodes);
return 0;
}
There is a cin in Create_router(argv[1],nodes), like cin>>r_size;
Many thanks in advance.
./prob < $2
means to redirect the input of the program to a file whose name is in the $2 variable.
If $2 is the actual input data, not a filename, then you should use a here-string:
./prob <<< "$2" ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
or a here-doc:
./prob <EOF ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
$2
EOF
or pipe the input to the program:
printf "%s\n" "$2" | ./prob ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
The here-string method is the simplest, but it's a bash extension. The other methods are portable to all POSIX shells.

cppman analog for C?

I'm new with C, so I'd like to use some manual pages directly from console.
Under Linux I can use cppman, to get tips about varios functions in C++, for example:
$ cppman printf | head -n 10
printf(3) C++ Programmer's Manual printf(3)
NAME
printf - Print formatted data to stdout
TYPE
function
Is there something lie this tool, but specially for C?
Because - there is some differents, for example:
$ cppman printf | grep -A 4 SYNOPSIS
SYNOPSIS
#include <cstdio>
int printf ( const char * format, ... );
UPD
Looking in man doesn't give results:
$ man 3 printf
No entry for printf in section 3 of the manual
$ man -k printf
...
printf (1) - format and print data
printf [builtins] (1) - bash built-in commands, see bash(1)
...
And also - printf here is just example, but whet about more complicated items?
For example:
$ man bool
No manual entry for bool
$ cppman bool | grep -A 8 EXAMPLE
EXAMPLE
// modify boolalpha flag
#include <iostream> // std::cout, std::boolalpha, std::noboolalpha
int main () {
bool b = true;
std::cout << std::boolalpha << b << '0;
std::cout << std::noboolalpha << b << '0;
return 0;
}
Regular old man will work. You can pass the -S3 option (or just 3) to restrict results to C standard library functions. If you don't see C standard library functions in your man results, you need to install the libc manpage collection.

How do I execute a string as a shell script in C++?

I'm writing a program that needs to be able to execute a shell script provided by the user. I've gotten it to execute a single shell command, but the scripts provided will be more complicated than that.
Googling got me as far as the following code snippet:
FILE *pipe;
char str[100];
// The python line here is just an example, this is *not* about executing
// this particular line.
pipe = popen("python -c \"print 5 * 6\" 2>&1", "r");
fgets(str, 100, pipe);
cout << "Output: " << str << endl;
pclose(pipe)
So that this point str has 30 in it. So far so good. But what if the command has carriage returns in it, as a shell script file would, something like the following:
pipe = popen("python -c \"print 5 * 6\"\nbc <<< 5 + 6 2>&1", "r");
With this my goal is that str eventually have 30\n11.
To put another way, assume I have a file with the following contents:
python -c "print 5 * 6"
bc <<< 5 + 6
The argument I'm sending to popen above is the string representation of that file. I want to, from within C++, send that string (or something similar) to bash and have it execute exactly as if I were in the shell and sourced it with . file.sh, but setting the str variable to what I would see in the shell if it were executed there, in this case, 30\n11.
Yes, I could write this to a file and work it that way, but that seems like it should be unnecessary.
I wouldn't think this was a new problem, so either I'm thinking about it in a completely wrong way or there's a library that I simply don't know about that already does this.
use bash -c.
#include <stdio.h>
int main()
{
FILE *pipe = popen("bash -c \"echo asdf\necho 1234\" ", "r");
char ch;
while ((ch = fgetc(pipe)) != EOF)
putchar(ch);
}
Output:
asdf
1234
(I've test on cygwin)

Piping input to an already running cpp program?

include
Lets assume that this is the code I am running:
int main(int argc, char **argv) {
bool running = true;
string lineInput;
while (running)
{
while (cin >> lineInput)
{
cout << lineInput;
}
}
return 0;
}
What I would like to have happen is that I can call start a program from terminal by typing "./myProgram" That part is fairly straight forward. The part I'm not sure how to do is make it so that I can at a later point in time type echo "some text to echo" | myProgram and be able to have my program then print that text back out to the terminal.
Right now I can only make it work if I type:
echo "blah blah blah" | ./myProgram
So my goal is to have two separate steps. One where I start my program, and a second when I pipe it some input to use
I'm thinking you could do this with a named pipe.
mkfifo mypipe
./myProgram < mypipe &
cat file1.txt file2.txt file3.txt > mypipe
You can use mkfifo, and just read from that in the program as from an ordinary file.
There's also
pipe or socket_pair (bi-directional)

Pipe an input to C++ cin from Bash

I'm trying to write a simple Bash script to compile my C++ code, in this case it's a very simple program that just reads input into a vector and then prints the content of the vector.
C++ code:
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<string> v;
string s;
while (cin >> s)
v.push_back(s);
for (int i = 0; i != v.size(); ++i)
cout << v[i] << endl;
}
Bash script run.sh:
#! /bin/bash
g++ main.cpp > output.txt
So that compiles my C++ code and creates a.out and output.txt (which is empty because there is no input). I tried a few variations using "input.txt <" with no luck. I'm not sure how to pipe my input file (just short list of a few random words) to cin of my c++ program.
You have to first compile the program to create an executable. Then, you run the executable. Unlike a scripting language's interpreter, g++ does not interpret the source file, but compiles the source to create binary images.
#! /bin/bash
g++ main.cpp
./a.out < "input.txt" > "output.txt"
g++ main.cpp compiles it, the compiled program is then called 'a.out' (g++'s default output name). But why are you getting the output of the compiler?
I think what you want to do is something like this:
#! /bin/bash
# Compile to a.out
g++ main.cpp -o a.out
# Then run the program with input.txt redirected
# to stdin and the stdout redirected to output.txt
./a.out < input.txt > output.txt
Also as Lee Avital suggested to properly pipe an input from the file:
cat input.txt | ./a.out > output.txt
The first just redirects, not technically piping. You may like to read David Oneill's explanation here: https://askubuntu.com/questions/172982/what-is-the-difference-between-redirection-and-pipe