6

Is it possible to access the original argv pointer from within a Haskell main?

My use case is that I'd like to remove command-line parameters after the application has started so they can't be read via ps. There are a few ways to do this but all require manipulating the originalargv.

I am able to do this if I write a C wrapper and call hs_init from there (afterwards mucking around with argv ala here), but it'd be nicer to do this from Haskell.

Thanks!

PS - this question is different from the duplicate as the duplicate uses a prctl which, as far as I can tell, only lets you change the process name. Further, the duplicate is looking to "set" argv[0] whereas I am trying to obtain a mutable reference to the original argv used to call the program.

Community
  • 1
  • 1
aaronlevin
  • 1,433
  • 2
  • 13
  • 18
  • 3
    My initial guess is that it isn't possible from Haskell since there is no `setArgs` function and `getArgs` returns an immutable list. – bheklilr Jan 02 '15 at 19:31
  • Thanks. I've been pouring over the FFI code and came to the same conclusion, but since I'm relatively new to this I didn't know if there was another way. – aaronlevin Jan 02 '15 at 19:34
  • 1
    This is something I didn't even know was possible 5 minutes ago, so there might be a way, but if there is a way it'll involve some strange corner function in an internal library. Look in the GHC specific libraries, since it'd likely depend on which compiler you're using. – bheklilr Jan 02 '15 at 19:36
  • @bheklilr this is what I've been doing. There are functions in `System.Environment` but they're not exported. I may end up re-writing some of them for this purpose, but wanted to check-in first. Thanks. – aaronlevin Jan 02 '15 at 19:38
  • 1
    [Try this](https://gist.github.com/ec78cc20e78479029812). I'm currently on windows so I don't think I can check it very accurately. Cygwin's ps doesn't show command line arguments at all, but Process Monitor catches everything that the process does so it records the command line args before you have a chance to overwrite it. Something along these lines might be what you're looking for. – bheklilr Jan 02 '15 at 20:09
  • @bheklilr hmm, I had something similar to this earlier and that didn't work, neither did yours :( – aaronlevin Jan 02 '15 at 20:29
  • If you're on a POSIX system you could 1) transfer all of the command line arguments to the environment, 2) `execve` yourself with no command line args and then 3) cleanse the environment; `execve` is available as `executeFile` in System.Posix.Process – ErikR Jan 02 '15 at 21:57
  • @amalloy I don't think that's a duplicate. It's close, but it uses a `prctl` which, as far as I can tell, only lets you change the process name. – aaronlevin Jan 02 '15 at 22:51

1 Answers1

0

I would look at the System.Posix.Env.ByteString(link) module from the unix package.

It contains functions to modify the environment and even though it only provides getArgs it shouldn't be difficult to add a setArgs function.

ErikR
  • 51,541
  • 9
  • 73
  • 124
  • This strategy doesn't seem to work. Try this code [here](https://gist.github.com/bheklilr/ec78cc20e78479029812), which is very similar to the `getArgs` method in `System.Posix.Env.ByteString`. Maybe this is related to some lazy evaluation? Not sure. – aaronlevin Jan 02 '15 at 21:26
  • hmmm... even if you add `getArgs >>= print` at the end the original args are printed. wonder why that's happening. – ErikR Jan 02 '15 at 21:46