echo (shell) and C language - c++

I have a program written in C language. In this program, I have an integer variable QS. The value of this variable changes during execution of the program
In this program written in C, I want to display this variable QS using the echo command shell
I heard about the system () function of the diaper C gives hand to use the terminal or console
system ("echo $ QS") when I do that, the variable QS is not recognized and it displays nothing.
Do you have any specific answers on how I could do this? and how to recognize the variable in C language?
I know that with a simple printf, I can display this variable, but what I want is to use echo.
Thank you in advance for your answers.

Shell can not access your program variable values. You have to set the value into the environment first. There are different ways to do this. One of them is (works in linux/unix)
int main()
{
char chProgramVar[] = "hello world" ;
setenv("ShellVar", chProgramVar, 1) ;
system("echo $ShellVar") ;
}

As others have said, the shell can't access your program variables. You can use sprintf to insert the value into the command that you will execute using system:
char command[BUFSIZ];
sprintf(command, "echo %d", QS);
system(command);

The shell you're spawning with the system(3) call has no idea about any of the variables in your C program. The easiest way to do what you want is to export your data as an environment variable. Since the environment is inherited by the call to system(3), you can just set the variable with setenv(3). However, you must first format it as a string:
int QS = ...;
char QSStr[32]; // Longest integer string is INT_MIN = -2147483648, assuming
// that sizeof(int) == 4
snprintf(QSStr, sizeof(QSStr), "%d", QS); // Convert to string
setenv("QS", QSStr); // Set the environment variable)
...
system("echo $QS"); // Will print the value of QS

You have to format the number as a character byte. The number "4" has a different integer representation as a printed character.
Use printf to print the number, or sprintf to reformat it as a character into a new buffer. Then you can print the new buffer using system echo (for whatever reason).
char s[16]; // might be too small
sprintf(s, "%d", integer_var);
// s is the string

Related

Why does getchar work like a buffer instead of working as expected in real-time

This is my first question on stackoverflow. Pardon me if I haven't searched properly but I do not seem to find an explanation for this. Was just attempting an example from Bjourne Stroustroup's papers. Added my bits to see the array get re-sized as I type the text.
But it doesn't seem to work that way! getchar() simply waits till I am done with entering all the characters and then it will execute the loop. As per the logic, it doesn't actually go into the loop, get a character, perform its actions and then iterate. I am wondering if this is implementation specific, or intended to be like this?
I am on Ubuntu 14.04 LTS using Codeblocks with gcc 4.8.2. The source was in cpp files if that matters.
while(true)
{
int c = getchar();
if(c=='\n' || c==EOF)
{
text[i] = 0;
break;
}
text[i] = c;
if(i == maxsize-1)
{
maxsize = maxsize+maxsize;
text = (char*)realloc(text,maxsize);
if(text == 0) exit(1);
cout << "\n Increasing array size to " << maxsize << endl;
}
i++;
}
The output is as follows:
Array Size is now: 10
Please enter some text: this is some sample text. I would have liked to see the memory being realloced right here, but apparently that's not how it works!
Increasing array size to 20
Increasing array size to 40
Increasing array size to 80
Increasing array size to 160
You have entered: this is some sample text. I would have liked to see the memory being realloced right here, but apparently that's not how it works!
Array Size is now: 160
This has nothing to do with getchar directly. The "problem" is the underlying terminal, which will buffer your Input. The Input is sent to the program after you press enter. In Linux (dunno if there is a way in Windows) you can workaround this by calling
/bin/stty raw
in terminal or by calling
system ("/bin/stty raw");
in your program. This will cause getchar to immediately return the input character to you.
Dont forget to reset the tty behaviour by calling
/bin/stty cooked
when done!
Here is an example (for Linux):
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main() {
system ("/bin/stty raw");
char c = getchar();
system ("/bin/stty cooked");
return 0;
}
Also have a look at this SO Post: How to avoid press enter with any getchar()
Also, as suggested in the comments, have a look here: http://linux.die.net/man/3/termios especially on the command tcsetattr, which should work cross-platform.
Actually, tcsetattr does not apply to Windows (which is what is commonly referred to in this site as "cross-platform"). However, the question is tagged for Linux, so "cross-platform" is a moot point.
By default the standard input, output and error streams are set to
line-buffered (input)
block-buffered (output)
line-buffered (error)
You can change that using setbuf, but of course will not solve the problem (the answer calls for single-character input). POSIX terminal I/O (termios) lets you change via a system call any of the flags shown using stty. As a rule, you might call stty directly from a script, rarely from a C program.
Reading a single character is a frequently asked question, e.g.,
How can I read single characters from the terminal? (unix-faq)
How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed? (comp.lang.c FAQ)
You could also use ncurses: the filter function is useful for programs that process a command-line (rather than a full-screen application). There is a sample program in ncurses-examples (filter.c) which does this.

Variables in quotation marks C++

Let me begin by saying that I could not find an identical question, but my search keywords were fairly generic, and so if you know of a thread that answers my question, point it out to me and I'll close this thread.
I'm re-writing a bash script of mine in c++ to help me get a firmer grasp on the language. The problem I'm running into is as follows:
string input = "/wam/wxx.cpp";
string output = "/wam/wxx.exe";
system ("/MinGW/bin/g++.exe input -o output");
(This is just a small illustration; in my actual code the variables are user-input)
Obviously I am passing the words 'input' and 'output' to my compiler instead of the variables of those names. I have tried
system ("/MinGW/bin/g++.exe" input "-o" output);
as well as other combinations of quoting/not quoting, none of which work either. The system command wants quotation marks, so is there a way to have my variables properly recognized in those quotes? (Currently I am saving these variables to a text file, then loading them into a bash script that runs the compiler, which defeats the purpose of me writing this in c++ to begin with.)
Thanks in advance!
EDIT: To clarify, I am
using namespace std
Since they are (presumably) std::string, you can just paste them together with +, like this:
std::string cmd = "/MinGW/bin/g++.exe";
std::string fullcmd = cmd + " " + input + " -o " + output;
system(fullcmd.c_str());
You need fullcmd.c_str() since system takes a C style string, not a C++ style string.
This should help:
string input = "/wam/wxx.cpp";
string output = "/wam/wxx.exe";
string command = "/MingW/bin/g++.exe "
command += input;
command += " -o "
command += output;
system(command.c_str());
You need std::string::c_str() to convert strings to char arrays, and you can't add an std::string to a string literal, however, you can add a literal to a std::string, or an std::string to an std::string.

how to add a space character to trigger var args c++ execlp()

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.

C++: How to escape user input for safe system calls?

On a Linux platform, I have C++ code that goes like this:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
std::string command;
command = "mkdir " + myDir;
if (system(command.c_str()) != 0) {
return 1;
}
// continue....
Is passing user input to a system() call safe at all?
Should the user input be escaped / sanitized?
How?
How could the above code be exploited for malicious purposes?
Thanks.
Just don't use system. Prefer execl.
execl ("/bin/mkdir", "mkdir", myDir, (char *)0);
That way, myDir is always passed as a single argument to mkdir, and the shell isn't involved. Note that you need to fork if you use this method.
But if this is not just an example, you should use the mkdir C function:
mkdir(myDir, someMode);
Using system() call with command line parameters without sanitizing the input can be highly insecure.
The potential security threat could be a user passing the following as directory name
somedir ; rm -rf /
To prevent this , use a mixture of the following
use getopt to ensure your input is
sanitized
sanitize the input
use execl instead of system to execute
the command
The best option would be to use all three
Further to Matthew's answer, don't spawn a shell process unless you absolutely need it. If you use a fork/execl combination, individual parameters will never be parsed so don't need to be escaped. Beware of null characters however which will still prematurely terminate the parameter (this is not a security problem in some cases).
I assume mkdir is just an example, as mkdir can trivially be called from C++ much more easily than these subprocess suggestions.
Reviving this ancient question as I ran into the same problem and the top answers, based on fork() + execl(), weren't working for me. (They create a separate process, whereas I wanted to use async to launch the command in a thread and have the system call stay in-process to share state more easily.) So I'll give an alternative solution.
It's not usually safe to pass user input as-is, especially if the utility is designed to be sudo'd; in order to sanitize it, instead of composing the string to be executed yourself, use environment variables, which the shell has built-in escape mechanisms for.
For your example:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
setenv("MY_DIR", myDir, 1);
if (system("mkdir \"${MY_DIR}\"") != 0) {
return 1;
}
// continue....

How do I print a UChar* var as a string from inside of gdb?

I've been doing some work on an unfamiliar codebase that uses UChar* as strings. Uchars are defined as follows (at least according to gdb)
(gdb) ptype UChar
type = short unsigned int
However, when I try to print these in gdb, I just get the address. I can also index into the pointer and retrieve the values of each character.
Is there any way to print a variable of type UChar* from within gdb and get back a meaningful string?
Also, this is on OS X, if that makes any difference.
Just define this command in your .gdbinit and type uc varname (uc will likely work as a short form for the ucharprint command you define)
define ucharprint
echo "
set $c = (unsigned short*)$arg0
while ( *$c )
if ( *$c > 0x7f )
printf "[%x]", *$c
else
printf "%c", *$c
end
set $c++
end
echo "\n
end
You don't need to worry about endianness since each unsigned short in your UTF-16 UChar type holds a code point (or half surrogate) as a native binary integer.
You first need to figure out what a UChar actually represents. It is likely UTF-16 or UCS-2 (but BE or LE?). Once you determine this, you want to provide (you can probably use existing code, such as iconv) a debug method to convert to UTF-8. See http://www.skynet.ie/~caolan/TechTexts/GdbUnicodePrinting.html for details.
print is the same as x;
x/1s 0x1234 -- will print out that location in memory as a string, if you keep hitting carrage return, it will print the next line... etc...
If you want to monitor something continually, use display/ with the same format specifier as x (print). "display/1s 0x1234" then every time you break via a breakpoint or a single step, you will see the information you configured print out .. updated etc...
if it is an ascii string, you might try to tell gdb to reinterpret:
(gdb) print (char*) theUcharPtr