I am trying to take an argument in the form of > in Linux.
I am trying to solve my problem ,like this :
std::string big(">");
if (argv[3]==big) {....}
But It doesn't work like this.
But It works like this:
std::string big("M");
if (argv[3]==big) {....}
I guess, I need to get ASCII CODE of my char and compare with argv[3]. But argv[3] it is type of a char , I connot compare int and char.
Can you help me?
Most shells (including the Windows CMD) handles symbols like <, > and | in a special way. < is input redirection, > is output redirection, and | is piping output from one process to the input of another.
Therefore you will never be able to get those symbols as arguments to your process, the command-line environment will use them and will not pass them on to your program.
Unix shells with background job support also adds & to the mix.
Related
I need to cut&paste a folder into another folder through code in C++. But some directory names are problematic, such as the ones which have japanese symbols. However, the same commands introduced through cmd all work fine.
system("move dirName dirName2"); //work
system("move ディレクトリ dirName2"); //does not work (system cannot find the specified file)
system("move ディレクトリ.txt dirName2"); //work
Funny enough, if the item which has the japanese symbols is a file and not a folder, the operation works fine even using calls to system().
I have no idea why the second call to system() does not work or how to solve it.
PS: I'm working with Windows7.
"move dirName dirName2", it is a const char* type, while the Japanese chars are not ASII chars, you should use the unicode API here, try:
_wsystem(L"move ディレクトリ dirName2")
It is likely that you need to use _wsystem instead to accomodate the wide characters. See the relevant MSDN pagefor details, but the syntax of the call is the same.
I'm writing this program on Ubuntu.
If I type this command into a shell
groups root sys bin
it outputs
root : root
sys : sys
bin : bin
However I'm writing a c++ program that calls groups with execlp using
execlp("groups", "groups", args.c_str(), NULL);
where args = "root sys bin". I just get a :No such user error since groups' is obviously just looking at that entire string as argv[0] which is the equivalent of running
groups "root sys bin"
How do i create the proper variable argument for execlp to run groups on each user, one at a time?
One option is to ask /bin/sh to deal with the input the way it normally would. Of course in addition to dealing with spaces, this would also deal with characters like $, #, ~, *, etc., which may or may not be what you want.
execl("/bin/sh", "sh", "-c", ("groups " + args).c_str(), nullptr);
Obviously, don't use this way if the data is user-entered and might contain nasty strings like:
root ;rm *
Otherwise, execl type functions won't work unless you know the number of command-line arguments at compile time. Assuming your args string could have varying numbers of arguments, you'll need execv type functions instead.
std::string args = "root sys bin";
std::vector<std::string> arg_vec;
std::istringstream arg_iss(args);
std::copy(std::istream_iterator<std::string>(arg_iss),
std::istream_iterator<std::string>(),
std::back_inserter(arg_vec));
char groups_exec[] = "groups";
std::vector<char*> arg_ptr_vec{ groups_exec };
std::for_each(arg_vec.begin(), arg_vec.end(),
[&](std::string& arg){ arg_ptr_vec.push_back(&arg[0]); } );
arg_ptr_vec.push_back(nullptr);
execvp("groups", arg_ptr_vec.data());
The args parameter to execlp is defined as "char *const argv[]", so I think you could do something like
const char *myArgs[3] = {"root, "sys", "bin"};
and then replace args.c_str() with myArgs.
I should admit to having zero experience of writing software for Ubuntu - this is what I would try next were I trying to get execlp to work.
EDIT: This is wrong - I had got mixed up and was looking at execv(), bobah and sleepy42 seem to have got it.
Question should say it all.
Let's say there's a local file "mydefaultvalues.txt", separated from the main project. In the main project I want to have something like this:
char * defaultvalues = " ... "; // here should be the contents of mydefaultvalues.txt
And let the compiler swap " ... " with the actual contents of mydefaultvalues.txt. Can this be done? Is there like a compiler directive or something?
Not exactly, but you could do something like this:
defaults.h:
#define DEFAULT_VALUES "something something something"
code.c:
#include "defaults.h"
char *defaultvalues = DEFAULT_VALUES;
Where defaults.h could be generated, or otherwise created however you were planning to do it. The pre-processor can only do so much. Making your files in a form that it will understand will make things much easier.
The trick I did, on Linux, was to have in the Makefile this line:
defaultvalues.h: defaultvalues.txt
xxd -i defaultvalues.txt > defaultvalues.h
Then you could include:
#include "defaultvalues.h"
There is defined both unsigned char defaultvalues_txt[]; with the contents of the file, and unsigned int defaultvalues_txt_len; with the size of the file.
Note that defaultvalues_txt is not null-terminated, thus, not considered a C string. But since you also have the size, this should not be a problem.
EDIT:
A small variation would allow me to have a null-terminated string:
echo "char defaultvalues[] = { " `xxd -i < defaultvalues.txt` ", 0x00 };" > defaultvalues.h
Obviously will not work very well if the null character is present inside the file defaultvalues.txt, but that won't happen if it is plain text.
One way to achieve compile-time trickery like this is to write a simple script in some interpreted programming language(e.g. Python, Ruby or Perl will do great) which does a simple search and replace. Then just run the script before compiling.
Define your own #pramga XYZ directive which the script looks for and replaces it with the code that declares the variable with file contents in a string.
char * defaultvalues = ...
where ... contains the text string read from the given text file. Be sure to compensate for line length, new lines, string formatting characters and other special characters.
Edit: lvella beat me to it with far superior approach - embrace the tools your environment supplies you. In this case a tool which does string search and replace and feed a file to it.
Late answer I know but I don't think any of the current answers address what the OP is trying to accomplish although zxcdw came really close.
All any 7 year old has to do is load your program into a hex editor and hit CTRL-S. If the text is in your executable code (or vicinity) or application resource they can find it and edit it.
If you want to prevent the general public from changing a resource or static data just encrypt it, stuff it in a resource then decrypt it at runtime. Try DES for something small to start with.
I am still new to C++ and am working out a way to open a program within my C++ program.
The problem is that whenever I have spaces in my paths, it sees it as different parameters.
int _tmain(int argc, _TCHAR* argv[])
{
system("C:\\Users\\blah\\Desktop\\a\\ b.txt");
return 0;
}
The output I receive is:
'C:\Users\blah\Desktop\a\' is not recognized as an internal or external command, operable program or batch file.
You can double quote your string literal. Edit: Also just noticed that your backslashes were not escaped so updated below :P
system("\"C:\\Users\\blah\\Desktop\\a\\ b.txt\"");
Also let it be known for the record that you really shouldn't use system. Try fork, spawn, or perhaps even the unofficial boost.process class which has functionality similar to .NET process class depending on your needs. Also think about why you need launch a process from a process ... perhaps you could make a library?
On Unix, you could use fork() + exec().
On Windows, check out spawn.
These execute the program directly, avoiding the command shell interpreter, thus avoiding any special treatment of special characters like spaces.
I'm currently developing an application that happens to require some file preprocessing before actually reading the data.
Doing it externally was not a possibility so I came up with a fork & execve of "cut options filename | sort | uniq -c" etc... and I execute it like that.
However I thought that maybe there was already another option to reuse all those ancient and good working tools directly in my code and not having to invoke them through a shell.
I am currently looking at busybox to see if there is an easy way of statically link and programatically call those utils but no luck yet.
Arkaitz, the answer no, because of how you've phrased the question.
You ask for "another option to reuse all those ancient and good working tools directly in my code and not having to invoke them through a shell"
The problem with that is, the proper and accepted way of reusing all those ancient and good working tools is exactly what you're saying you want to avoid - invoking them via a shell (or at least, firing them up as child processes via popen for example) - and it's definitely not recommend to try to subsume, copy, or duplicate these tools into your code.
The UNIX (and Linux) model for data manipulation is robust and proven - why would you want to avoid it?
The 'ancient' tools were built for use by the shell, not to be built/linked into an executable. There are, however, more recent tools that kinda do lot of what you showed on your command line preprocessor: iostreams with extractors (to replace cut), std::sort and std::unique to replace the respective programs...
struct S { string col1, col3;
bool operator<( const S& s ) { return col1 < s.col1; }
};
vector<S> v;
while( cin ) {
S s;
string dummy;
cin >> s.col1 >> dummy >> col3 >> dummy;
v.push_back( s );
}
sort(v.begin(), v.end(), S::smaller );
unique( v.begin(), v.end() );
Not too complicated, I think.
Try popen().
char buffer [ BUFFER_SIZE ];
FILE * f = popen( "cut options filename | sort | uniq -c", "r" );
while( /*NOT*/! feof(f) )
fgets( buffer, BUFFER_SIZE, f );
pclose( f );
Reference: How to execute a command and get output of command within C++ using POSIX?
You have to do it through the shell, but it's easier to use "system" call.
while(something) {
int ret = system("foo");
if (WIFSIGNALED(ret) &&
(WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
break;
}
Just write another useful 'ancient and good' tool ;) and read all data from stdin and return it to stdout.
cat *.txt | grep 'blabla' | sort | my_new_tool | tee -o res_file
The nice way to do it is:
Create 2 pipes
Fork a new process
Replace stdin and stdout for child process with pipes using dup2 function
exec a command you'd like
Write and read from parent process using pipes
busybox was my first thought as well, although you might also want to consider embedding a scripting engine like Python and doing these kind of manipulations in Python scripts.
I would definitely not try to strip this kind of functionality out of GNU command line tools since they have grown significantly since the early UNIX days and sprouted an awful lot of options.
If the busybox code seems too hard to adapt, then the next place I would look would be Minix source code. Look under Previous Versions and pick one of the version 1 or 2 Minixes because those were written as teaching code so they tend to be clearer and simpler.
If you do not want to call external commands (whether by exec, popen or system etc) but do not want to modify the source of these utilities and compile them into your code (relatively easy, just change 'main' to 'main_cut' etc), then the only remaining option I see is to embed the utilities inside your code and either extract them at runtime or dynamically create a filing system by pointing at the data inside your code (eg using a floppy or cd image and writing a FUSE module that picks up the disk image data from a ram address). All of which seems like a lot of work just to make this look like a single neatly-packaged utility.
Personally, if i really had to do this, I'd get the source of all those utils and compile them in as external calls. Of course you'd no longer have pipes easily available, you'd either have to use temp files for preprocessing, or something more complicated involving co-routines. Or maybe sockets. Lots of work and messy whatever you do!