romaric crailox
romaric crailox

Reputation: 584

access to process' arguments outside main()

Is it possible to access process' arguments elsewhere than inside main function ?

I am in a situation where I can't add code in main function. A test software create for me a test driver program and I can add code only inside specific part of test driver program (that is not main function). I want, in this code, change process arguments (to be precise, I want to change process name after a fork…)

Upvotes: 3

Views: 257

Answers (3)

Emmanuel DUMAS
Emmanuel DUMAS

Reputation: 700

Other solution only for linux, use /proc/NNN/cmdline. Example :

int pid;
char procPathName[256];
int fcl;

pid = getpid();
snprintf(procPathName, 255, "/proc/%ld/cmdline", pid);
fcl = open(procPathName, 0);
if (fcl == -1)
{
  /* error */
}
else
{
  char buffer[1024];
  int bufferLen;
  bufferLen = read(fcl, buffer, 1023);
  close(fcl);
}

Upvotes: 1

rici
rici

Reputation: 241909

There is no portable way to access the value of argv other than saving it on entry to main(), which is not possible under the conditions of the question.

However, non-portable solutions exist for most operating systems, based on the expected layout of the initial stack. For example, the following should work on Linux (but no guarantees, neither explicit nor implied):

#include <stdint.h>
/* This code is unsafe and unportable. But it might work for you. */
char** getargv(void) {
  extern char** environ;
  char **argv = environ - 1;
  for (char** e = argv; (uintptr_t)(argv[-1]) != e - argv; --argv) { }
  return argv;
}

That code comes from reverse-engineering the stack created here. It assumes that environ still has the value assigned at startup, which may not be the case if the application has called setenv or putenv before this function is called. (Those are pretty rare, though.) For reference, the relevant part of the stack looks like this (all entries are the size of a pointer):

argc
argv[0]
...
argv[argc - 1]
0
environ[0]
...
0

The loop starts at the NULL terminating the argv array and looks backwards until it comes across an integer which would be a correct value for argc. It could be fooled by an address which looks like an integer but in Linux that is extremely unlikely because the addresses used for the argv strings are never small enough to be confused with a small integer.


The code above is written as a function but in the context of the question that might not be possible. Obviously, it could just be copied into some other function, so it's not a problem.

However, if you are able to insert a function and a global into the executable, you can take advantage of the usual (but not universal) implementation of constructor functions, using the GCC/Clang constructor function attribute. Any such functions are executed prior to main() being called, and are passed the same arguments as main() is passed. This should work at least on Linux and OS X, and quite possibly other Unix-like systems:

char** saved_argv;
int saved_argc; 
void saveargv(int argc, char** argv) __attribute__((constructor)) {
  saved_argc = argc;
  saved_argv = argv;
}

Upvotes: 4

siz
siz

Reputation: 134

You can backtrace the stack and go upto to main(if you can find it), there u get arg values then change them

Upvotes: 0

Related Questions