So I've been trying to access command line arguments with indices larger than argc in C++ (because why not) and discovered that there are actually some parameters passed on to the program. The following code produces the following result in my Ubuntu 14.04:
#include <cstdio>
int main (int argc, char** argv) {
for (int i=argc+1; argv[i]!=0; i++)
printf("%3d %s\n", i, argv[i]);
}
This is the output:
2 XDG_VTNR=7
3 LC_PAPER=tr_TR.UTF-8
4 LC_ADDRESS=tr_TR.UTF-8
5 XDG_SESSION_ID=c2
6 XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/kubuzetto
7 SELINUX_INIT=YES
8 LC_MONETARY=tr_TR.UTF-8
9 CLUTTER_IM_MODULE=xim
(and so on)
What is this and is it distro-dependent?
Don't run past argc, it's not defined.
In this case, we know what happened. You see, main() is declared and called as
extern int main(int argc, char **argv, char **envp);
and it just so happens that the the way argv and envp are built leaves envp right after argv, so running off the end encounters envp.
It might change someday, so don't depend on this working. If you wanna depend on the kernel's passing method, provide the kernel's entry point yourself (which must be done in asm [or possibly a naked function] as it doesn't look like a function call).
Related
I want to use parameters in a program I made in C/C++ languages. Example:
MaxPayne2.exe -developer -developerkeys
I want to use a parameter like this in my exe file. How can I do it?
https://en.cppreference.com/w/cpp/language/main_function
While I would usually recommend adding more context this is your answer.
The standard c++ main has two additional parameters,
int main (int argc, char *argv[]) { }
To use these "arguments" (as they are called) you just reference their point in the argv array.
argc = the number of additional arguments supplied.
argv = the array of argument values supplied.
Example:
int main (int argc, char *argv[])
{
cout << argv[argc-1]; //Prints out the last argument supplied.
}
(note)If my syntax is wrong someone please correct me, my c++ is a bit rusty.
Running :
int main(int argc, char** argv){
char* file_one = malloc(10);
char* file_two = malloc(10);
strcpy(file_one, argv[1]);
printf("file_one addresss is: %p\n", file_one);
printf("file_two addresss is: %p\n", file_two);
printf("Difference is %ld\n", (file_two-file_one));
printf("File_two has: %s", file_two);
free(file_one);
free(file_two);
}
and running it using different values insted of 15:
./heap_overflow $(python -c "print('A'*15+'koko')")
cause glibc to raise different errors (sometimes munmap_chunk sometimes double free or corruption) and exit. also overflowing buffer by more than 10 but less than a specific number seems to do Nothing so what exactly are these mechanisms and how they work. I guess they are like stack canaries but can't see why their behavior is different when overflow amount differs. and if so where are they place in relation to difference.
I'm developing my own version of getopt() in assembly and trying to get my head wrapped around this snippet, specifically line 476
if (argc < 1)
return -1;
As the normal calling convention would be something like this;
int c = getopt( argc, argv, "vm:drx:");
and assuming the programmer hasn't done anything with argc before hand, the only reason I can think it would be there is that some flavor of Linux, possibly non POSIX compliant would'nt pass argv[0] application path & name. Therefore, argc could be zero. Is there any credence to this conjecture?
Of the 12 times this variable is used in this procedure, it's only ever asserted or copied, never modified and not referenced at all in the two levels of procedure before this.
Consider this:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
execve("./testargc", NULL, NULL);
}
And this program:
#include <stdio.h>
int main (int argc, char* argv[])
{
printf("%d\n", argc);
}
The first one execs the 2nd one with no arguments. The pathname is not passed in and as a result argc is 0.
I need to pass 1 value between programs. In my case, I run (VERY SIMPLE) program within another by calling system("SimpleProgram").
Is there a way how to pass 1 value (integer) returned by SimpleProgram. Neither "return 123" nor "exit(123)" doesnt work.
Is there any elegant way to pass such value? (I dont want to write and read an external file)
EDIT:
The language is C++, the programming is done on BeagleBone with Angstrom distribution.
retCode = system("cd /home/martin/uart/temp/xml_parser && ./xmldom");
Note what the man page for system(3) says about the return code:
The value returned is -1 on error (e.g. fork(2) failed), and the
return status of the command otherwise.
This latter return status is in the format specified in wait(2). Thus, the exit code of the command will
be WEXITSTATUS(status).
So you're almost there. If you have a simple program that returns 123, as you stated:
int main(int argc, char **argv) {
return 123;
}
then you can run it with system(3) and see its return code by using WEXITSTATUS():
#include <iostream>
using namespace std;
#include <stdlib.h>
int main(int argc, char **argv) {
int rc = system(argv[1]);
cout << WEXITSTATUS(rc) << '\n';
}
Naming the first program return123 and the second system:
$ ./system ./return123
123
If you leave off the WEXITSTATUS() and just print rc directly, you will get an incorrect value.
The standard way to do this is with UNIX pipes.
If it's just a hack, you might as well just use the binary return value, but in either case, you'd have to use execve() instead of system().
hi i have an c function
int main(int argc, char *argv[])
and my wrapper.c has this function
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jint argc, jcharArray argv) {
return main(argc, argv);
}
and in java i've defined it like this
private native int lameMain(int argc, char[] argv);
but i think i'm doing something wrong with the argv-argument... it's not an char-array, but a array of char-pointers.
can anyone help?
when i run it my app crashes with
03-20 23:26:23.487: A/libc(30436): Fatal signal 11 (SIGSEGV) at 0xfd90001d (code=1), thread 30436 (package)
On the Java side, convert the array to an array of strings (i. e. String[]). Pass it like that. On the JNI side, go through the array and retrieve the characters of each string. The declarations would go like this:
private native int lameMain(String[] argv);
And in C:
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jobjectArray argv )
There's no need to pass argc, because Java arrays store their own size.
That said, you're probably doing something very wrong. Typical Android programs don't start with main and don't take command line arguments - they have activities instead. A C main() function is a starting point of a program, but since you're calling it from the Java side, it's not the first thing in the program.
EDIT: Okay, but I still think you're doing this wrong on more than one count. I take it, the encoder takes a file - right? So you save the wave from memory into a file just to be read again? That's lame (pun intended).
Also, do you really need to pass an arbitrary sized array from the Java side? If you know the number of arguments at design time, and it's small (say, two), it's much, much easier to just pass two jstrings.
Anyway, here goes the array stuff. This assumes the sources of your JNI library are C++, not C. For C, the invokation of JNI functions would be slightly different, and you'd have to use malloc/free instead of new/delete.
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jobjectArray jargv)
{ //jargv is a Java array of Java strings
int argc = env->GetArrayLength(jargv);
typedef char *pchar;
pchar *argv = new pchar[argc];
int i;
for(i=0; i<argc; i++)
{
jstring js = env->GetObjectArrayElement(jargv, i); //A Java string
const char *pjc = env->GetStringUTFChars(js); //A pointer to a Java-managed char buffer
size_t jslen = strlen(pjc);
argv[i] = new char[jslen+1]; //Extra char for the terminating null
strcpy(argv[i], pjc); //Copy to *our* buffer. We could omit that, but IMHO this is cleaner. Also, const correctness.
env->ReleaseStringUTFChars(js, pjc);
}
//Call main
main(argc, argv);
//Now free the array
for(i=0;i<argc;i++)
delete [] argv[i];
delete [] argv;
}