/usr/bin/env: node: No such file or directory , c++ - c++

i am writing some functions on c++ for compiler less to css.
i installed nodejs, less.
i created a less file test.less
#color: red;
a{color:#color;}
when i run command on terminal:
lessc test.less test.css
it created a files css with name is test.css, but when i run this command via c++, it return a error. please help me. this is my c++ function:
std::string shell_exec( std::string cmd )
{
std::string result = "";
FILE* pipe = popen(cmd.c_str(), "r");
if (pipe == NULL)
{
return result;
}
char buffer[128];
while(!feof(pipe))
{
if(fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
pclose(pipe);
return result;
}
shell_exec("lessc test.less test.css");
i got a error:
/usr/bin/env: node: No such file or directory
/usr/bin/node is existed.
================ UPDATE: Fixed==================
Thank you #Bass Jobsen , #Lightness Races in Orbit
i fixed by add absolute path to lessc and nodejs
shell_exec("/usr/bin/node /usr/bin/lessc test.less test.css");

From: https://unix.stackexchange.com/a/29620
The advantage of #!/usr/bin/env python is that it will use whatever
python executable appears first in the user's $PATH.
So you should add node to the $PATH of the user that runs your script, see: https://stackoverflow.com/a/13210246/1596547
Notice that i can not compile your code, but i can when using the following code:
int main()
{
std::string r = shell_exec("lessc test.less test.css");
}
Probably also use using namespace std and string instead of std:string.

Related

Redirect ffmpeg console output to a string or a file in C++

I'm trying to use ffmpeg to do some operations for me. It's really simple for now. I want to omit the ffmpeg output in my console, either redirecting them to strings or a .txt file that I can control. I'm on Windows 10.
I have tried _popen (with and "r" and "w") and system("ffmpeg command > output.txt")', with no success.
#include <iostream>
#include <stdio.h>
using namespace std;
#define BUFSIZE 256
int main()
{
/* 1.
x = system("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4 > output.txt");
*/
/* 2.
FILE* p;
p = _popen("ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4", "w");
_pclose(p);
*/
/* 3.
char cmd[200] = { "ffmpeg -i video.mp4 -i audio.mp4 -c copy output.mp4" };
char buf[BUFSIZE];
FILE* fp;
if ((fp = _popen(cmd, "r")) == NULL) {
printf("Error opening pipe!\n");
return -1;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Do whatever you want here...
// printf("OUTPUT: %s", buf);
}
if (_pclose(fp)) {
printf("Command not found or exited with error status\n");
return -1;
}
*/
return 0;
}
Further in the development, I would like to know when the ffmpeg process finished (maybe I can monitor the ffmpeg return value?) or to display only the last line if the some error occurred.
I have made it to work.
In the solution 1, I added " 2>&1" to the end of the string.
Found it here: ffmpeg command line write output to a text file
output-to-a-text-file
Thanks!

Creating folders in C++

I have recently started working in C++ and came across this situation when I have to create a directory while executing my code. The code is working fine when I have to create a single folder but it fails when I have to create another folder withing this newly created folder.
Suppose, I am in C: and want to store my file in C:/A/B/ .The following piece of code using mkdir() works fine if I have to store my file in C:/A/ but fails when I am adding another folder B.
Following is my code snippet:
#include <sys/stat.h>
#include <string>
using namespace std;
int main()
{
string stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
if(status!=0)
{
//.....
}
else
{
//....
}
}
Can someone help me in creating this directory where I can have any number of folders inside the parent directory? (P.S:I have added the header files sys/stat.h,iostream and string)
This is how you do it in C++17:
#include <filesystem>
namespace fs = std::filesystem;
fs::create_directories("./a/b/c")
mkdir() creates only the last component of the specified path. In your example, it will create only B. If any of the parent directories do not exist (ie, if A does not exist), the function fails with ENOENT. You need to split up the path and call mkdir() for every intermediate directory in the path, ignoring EEXIST errors as you go.
status = mkdir("C:/A/", 0777);
if ((status < 0) && (errno != EEXIST)) ...
status = mkdir("C:/A/B/", 0777);
if ((status < 0) && (errno != EEXIST)) ...
If you don't want to handle this manually, use a wrapper that handles it for you, such as Boost's create_directories() function:
bool create_directories(const path& p);
bool create_directories(const path& p, system::error_code& ec);
Effects: Establishes the postcondition by calling create_directory() for any element of p that does not exist.
Postcondition: is_directory(p)
Returns: true if a new directory was created, otherwise false.
Throws: As specified in Error reporting.
Complexity: O(n+1)where n is the number of elements of p that do not exist.
You can call the following:
string stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
If
C:/A/ directory exists. If its not exists, then do the following:
string stringpath = "C:/A/";
int status = mkdir(stringpath.c_str(),0777);
stringpath = "C:/A/B/";
int status = mkdir(stringpath.c_str(),0777);
In C++11 you can use the experimental functios:
#include <experimental/filesystem>
...
std::stringstream bufH;
bufH << dirName << fName;
if (!std::experimental::filesystem::exists(bufH.str()))
{
std::experimental::filesystem::create_directories(bufH.str());
}
Try the octal flag 7777 like this to have all the rights necessary to create this folder.
int status = mkdir(stringpath.c_str(), 7777);
Or do a chmod in the A folder like that :
chmod -r 7777 *

running same script for 2 different files (input & output) ??? /ROOT/C++

I have a script that reads a tree and creates some plots.
I have two files I need to run, so I need to run the same script once for file1 and once for file2, storing results in a different output file each time.
How can I tell my program what file to run each time and where to save the results?
file1 is: flatTree_jetHT
outputfile1 is: flatTree_JetHT_output.root
file2 is: flatTree_jetHT2
outputfile2 is: flatTree_JetHT2_output.root
I need to write this down using just one void and telling which file to run from terminal (.x flatTree_jetHt_read.C)
Here is my code:
#include <iostream>
void flatTree_jetHT_read()
{
gROOT->Reset();
gROOT->SetStyle("Plain");
gStyle->SetOptStat(1);
gStyle->SetOptFit(0);
gStyle->SetPadColor(0);
gStyle->SetPalette(1);
TFile *f = TFile::Open("flatTree_JetHT.root", "READ");
TTree *tree = (TTree*)f->Get("boosted/events");
TFile *outf = TFile::Open("flatTree_JetHT_output.root", "RECREATE");
//more code....
}
Have you tried just passing the input/output as arguments of the function? (see the Getting Started section of the user guide).
void two_args(const char* input_file, const char* output_file)
{
printf("Input: '%s'\n", input_file);
printf("Output: '%s'\n", output_file);
}
then run as
$ root -l -x -q '/tmp/two_args.C+("in.root", "out.root")'

stat() doesn't find a file in c++

on Linux 12.04
I have an executable file located in say:
/a/b/exe
and a config file on
/a/b/config
when doing:
cd /a/b/
./exe
everything's ok and the stat function finds the file config on /a/b/
HOWEVER,when running from root
/a/b/exe
the stat doesn't find the config file
any idea why?
it makes it impossible to run the binary using a script that isn't ran from the folder of the exe.
Edit
The call looks like this:
struct stat stFileInfo;
bool blnReturn;
int intStat;
// Attempt to get the file attributes
intStat = stat(strFilename.c_str(),&stFileInfo);
if(intStat == 0) {
// We were able to get the file attributes
// so the file obviously exists.
blnReturn = true;
} else {
// We were not able to get the file attributes.
// This may mean that we don't have permission to
// access the folder which contains this file. If you
// need to do that level of checking, lookup the
// return values of stat which will give you
// more details on why stat failed.
blnReturn = false;
}
In first case cd ..., run exe you change current working directory before executing the program, in second case you launch exe without changing current working directory, and I think in your program you use a relative path to open your config(for example ./config or just config) and it can't find it from current working directory. easiest workaround is to change working directory at start of your app:
int main(int argc, char** argv) {
std::string s( argv[0] ); // path to the program
std::string::size_type n = s.rfind( '/' );
if( n != std::string::npos ) {
std::system( ("cd " + s.substr(0, n)).c_str() );
}
// rest of your code
}

How do I change the execution PATH of a process programatically?

I am working on a mini-shell, and am trying to set the execution path dynamically.
I am using setvar() to set the PATH and when I check it with getvar() it reads the new PATH.
Here are the two things I tried to execute:
1. I change the PATH to /bin which I know contains most system functions, but no programs can work. I can also verify that the path has been set in the environment. I execute the commands using execvp()
2. I then used extern char** environ to get the environment and pass it into execvpe() but it still doesn't work.
I solved this by using istringstream to manually search the PATH and then use that to execute the process:
string dir;
string path = get_var("PATH");
istringstream search(path);
while(search.good()) {
getline(search, dir, ':');
if(dir != "") {
struct stat st;
if(dir[dir.length()] != '/') dir.append("/");
string file = dir + cmdArg[0];
//is file in dir?
if(stat(file.c_str(), &st) == 0) {
execvp(file.c_str(), cmdArg);
}
}
}