command line arguments - how to put them on the receivers st

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

command line arguments - how to put them on the receivers st

Post by distantvoices »

There is this question which occupies a part of my thinking:

Where do I put the data of command line arguments and how do I transfer them to the receiving process?

do I put them as a whole on the receiving stack?

do I copy them piece by piece to an arbitrary location in memory, prior to the new process image and then toss pointers onto the stack? (this one seems :-/ to me->after abit of reading... it seems to be like that and an array of pointers is located on the stack)

For pointers to the right direction I say thanks in advance.

Now I set off and look at my own documention about argc and argv[] maybe i can deduce a bit from it.

stay safe :-))
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
HOS

Re:command line arguments - how to put them on the receivers

Post by HOS »

i was wondering about this and so far have been planning (but not implementing yet) to use the new process's heap space to allocate a region for a string/a few strings and then push the pointers to these strings on the app's stack. would this be an ok way to do it?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:command line arguments - how to put them on the receivers

Post by Pype.Clicker »

Let's say you reserve in your programming model a region of x KB of virtual addresses to store arguments, environment and the like. When passing argument, the system may just be using that region with a top-down or bottom-up policy: arguments need not to be freed in any way.

When the 'values' of the argument are all there (or before placing them), it can also store there address from that 'tank' in the ARGV array (also located in the tank), and then pass just the size and the address of the ARGV array on the stack of the function.
Tim

Re:command line arguments - how to put them on the receivers

Post by Tim »

Mobius does this similar to how Pype describes.

For example, when the shell starts an application:
-- Shell calls ProcSpawnProcess in the kernel, passing a command line. ProcSpawnProcess creates a new process_t object. It allocates a process_info_t in kernel space and copies the command line there. A thread is created in the new process.
-- The new thread starts and immediately page faults because its EIP is set to 0xdeadbeef. The page fault handler notices this and calls ProcFirstTimeInit.
-- ProcFirstTimeInit allocates a block of memory in user mode (remember this is a fresh, clean address space). It copies the new process's process_info_t -- including the command line --into there. It frees the kernel-mode process_info_t.
-- Execution continues at the application's main entry point, which looks something like this:

Code: Select all

void start(void)
{
    wchar_t *cmdline = ProcGetProcessInfo()->cmdline;
    wchar_t **argv;
    int argc;
    argc = __crt0_parse_args(cmdline, &argv);
    return exit(wmain(argc, argv));
}
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:command line arguments - how to put them on the receivers

Post by distantvoices »

This tells me following:

1. Upon building the process sturcture, it gets also an area assigned to, where cmd_line arguments are stored in a looong string. This splitting between command and arguments - I've already done it in my shell in order to be able to say "cd [dir]" - works like a weasleys wizarding wheeze.

2. Upon startup of the process, a function comes into play which first picks that string from the process structure and tosses it to another one which splits the loong string into a bunch of small ones (which are (? here i am unsure) the whole string, split up with '\ 0' in stead of spaces - so the spaces are the delimiter for each argument.) I just toss the start adress of the next string to the array argv and increase argc by one.

-- is the argument area in the process struct to be freed after retrieval? would make sense, hm?

Gonna try this one today...

stay safe
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:command line arguments - how to put them on the receivers

Post by Pype.Clicker »

iirc, in Unix, it's up to the caller of execve to split strings from the looong cmdline.
int execve(const char *filename, char *const argv [], char
*const envp[]);
And the system will just keep that splitting. This makes more sense because some shell will allow you to escape spaces (in filename, for instance) or to provide "here strings", etc. You do not want the OS to split such "here strings" while passing arguments and the OS do not want to bother with escapes, quotes and the like.

So just have the shell giving an array of string pointers makes everyone happy ;-)
Tim

Re:command line arguments - how to put them on the receivers

Post by Tim »

Mobius is non-Unix in this respect: to start a process, you pass a big ol' command line string, and it's up to the app to parse it.

Whereas this requires that the C library provide command line parsing code, it means that an application can handle its command line regardless of the way the shell would parses it.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:command line arguments - how to put them on the receivers

Post by Candy »

beyond infinity wrote: 2. Upon startup of the process, a function comes into play which first picks that string from the process structure and tosses it to another one which splits the loong string into a bunch of small ones (which are (? here i am unsure) the whole string, split up with '\ 0' in stead of spaces - so the spaces are the delimiter for each argument.) I just toss the start adress of the next string to the array argv and increase argc by one.

-- is the argument area in the process struct to be freed after retrieval? would make sense, hm?
As for where to put them, I think you can best put them at the end of the .bss, and tell the program it's a part of itself. It should be split up into parts even before it's in the kernel, so the method of splitting it up depends on the application you entered it in, not the application you are addressing (consistent interface, enforce some good issues on the users).

You can only be sure it's been retrieved when main exits, and that only happens when the process itself terminates. In other words, you cannot.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:command line arguments - how to put them on the receivers

Post by distantvoices »

Finally, I've managed to do the command line argument stuff:

I do it the following way:

1. the shell splits the command line in chunks of strings (limited by '\0') and stores the adress in the argv array.

2. then, upon calling execve, I pass the argv array as well as the name of the executable.

3. the execve interface counts the number of args stored in argv and calls do_execve (the work horse), which builds a stack image:

4. do_execve makes some sanity checks: is nr of args < 60, and is commandline < 1024 f. ex. then, it allocates some memory on the heap and starts building a stack image:
first, the argv_array: the adresses there are replaced by offsets of the start of the corresponding argument to the start of the stack image. then, a zero is added to the argv array. After that, each string adressed in the passed argv array is copied to the stack image - directly after the argv.

5. Upon performing the actual exec, mmsrv copies the stack image from the process to an internal buffer and performs the following:
a) subtract nr_of_stackbytes from stacktop (f. ex. 0xb000ffff) -> say this is stack_start.
b) walk throu the buffered stack image and replace all the offsets in argv (except the very first position, which is argc) by offset in argv+stack_start(which is our base).

6. This image, you copy into the process stack area.

7. Upon process startup, you have a stub in asm, which first saves the according pointers (esp, esp+4) in registers - to push them prior to call to int main(argc,argv);

Hope this helps.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
Post Reply