[comp.lang.c] Destroying arguments

dusan@osupyr.UUCP (Dusan Nedeljkovic) (05/09/87)

I'm looking for a way to modify/destroy agruments passed to a C program
on the command line.  I guess this would be similar to what crypt(1) does
if a key is passed to it on the command line.  

Any ideas?

-- 

Dusan Nedeljkovic
*       dusan@osupyr.uucp       **      ...cbatt!osupyr!dusan       *
Remember:  "These are the good old days."

john@polyof.UUCP ( John Buck ) (05/14/87)

In article <292@osupyr.UUCP>, dusan@osupyr.UUCP (Dusan Nedeljkovic) writes:
> I'm looking for a way to modify/destroy agruments passed to a C program
> on the command line.  I guess this would be similar to what crypt(1) does
> if a key is passed to it on the command line.  
> 

For each argv[] element you wish to destroy, simply copy another (any)
string (or string of characters) over it using strncpy() or a pointer
assignment loop:
   /* Note that the strlen() of any argument must not exceed the length
    * of the string of zeroes "00000000....0000"
    */
   for(i = 0; i < argc; i++)
      strncpy(argv[i], "0000000000000000000000000000000", strlen(argv[1]));

Note that you can't copy a string longer than the original argv[].
(You would scribble past the end!)

Also note, if you are trying to mask the name of the program you are running,
(namely, argv[0]), this method is not fool-proof.  Some version of "ps"
will print the u.u_comm field from the process' user structure.  This field
contains the basename of the program you are executing, and, there is no
way to change it short of an exec() type system call.

John Buck
polyof!john

itkin@bene.UUCP (Steven List) (05/17/87)

In article <239@polyof.UUCP> john@polyof.UUCP ( John Buck ) writes:
>In article <292@osupyr.UUCP>, dusan@osupyr.UUCP (Dusan Nedeljkovic) writes:
>> I'm looking for a way to modify/destroy agruments passed to a C program
>> on the command line.
>For each argv[] element you wish to destroy, simply copy another (any)
>string (or string of characters) over it using strncpy() or a pointer
>assignment loop:

Without commenting in detail on John's reply, I would note that since
argv is an array of POINTERS to strings, the simple thing to do is to
set up your own string and then store the address/pointer in argv[n].
This avoids the potential pitfalls that John's method involves and gives
you the option to store ANYTHING YOU WANT in the argument list.

I'm curious as to WHY you want to modify/destroy command line arguments?
Another note - if you want to remove a command line argument (so it won't 
show up in a ps for instance), you can just copy pointers up in the array.

chris@mimsy.UUCP (Chris Torek) (05/18/87)

In article <485@bene.UUCP> itkin@bene.UUCP (Steven List) writes:
>... since argv is an array of POINTERS to strings, the simple thing
>to do is to set up your own string and then store the address/pointer
>in argv[n].  This avoids the potential pitfalls that John's method
>involves and gives you the option to store ANYTHING YOU WANT in
>the argument list.

Alas, this wonderfully simple technique simply does not work with
the 4BSD `ps', which reads the strings themselves, not the pointers
thereto.  An extremely long argv, or a long environment, *will*
confuse ps; it is sometimes possible simply to store a valid pointer
into argv[argc].  This is not, however, something I would rely
upon.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

guy%gorodish@Sun.COM (Guy Harris) (05/18/87)

This really isn't a C question at all, it's a UNIX question, so I'll
redirect it where it should have been sent in the first place.

> Newsgroups: comp.lang.c
> Distribution: comp.unix.questions

In fact, it looks like the orignal poster may have tried directing it
there, but goofed.

> Alas, this wonderfully simple technique simply does not work with
> the 4BSD `ps', which reads the strings themselves, not the pointers
> thereto.

As do most other versions of "ps".  The 3B2 version of "ps" does it
differently; the kernel stashes a string away in the U area that
contains the original arguments used to invoke the program.  (I have
no idea whether this was done because somebody thought this was the
right way to do things, or because they couldn't figure out how to
snarf the arguments up on a machine whose stack grows upward in
memory....)  On this machine, you *can't* smash your argument list.
Period.

The answer is "forget it".  In general, it can't be done.  Some
versions of "crypt" write '\0' all over the password it is handed,
which means it'll smash the argument if that was where the key
appeared, but 1) this won't work on a system that works the way 3B2
UNIX does and 2) still leaves a window in which the argument can be
seen.

We won't mention that it also leaves the encryption key on your
screen when you type the command, or that using "crypt" in this
fashion in a *script* is a very bad mistake as it leaves the
encryption key in a file.  In short, the answer is "always get
encryption keys from the user, and turn off echoing when you do so".

jfh@killer.UUCP (John Haugh) (05/19/87)

In article <485@bene.UUCP>, itkin@bene.UUCP (Steven List) writes:
> In article <239@polyof.UUCP> john@polyof.UUCP ( John Buck ) writes:
> >In article <292@osupyr.UUCP>, dusan@osupyr.UUCP (Dusan Nedeljkovic) writes:
> >> I'm looking for a way to modify/destroy agruments passed to a C program
> >> on the command line.
> >For each argv[] element you wish to destroy, simply copy another (any)
> >string (or string of characters) over it using strncpy() or a pointer
> >assignment loop:
 
Yes, this is a more correct way.  Some versions (all of the few ones that
I have seen) of PS(1) print out the arguments by looking in the stack
segment for the strings themselves.  Destroying the strings requires that
you modify the strings themselves.  This removes the possibility that the
PS(1) you are using does look at the stack.  However - some options of
PS(1) look in the U-page (u_command?) for the name of the command, and
that can't be (easily) changed.

> Without commenting in detail on John's reply, I would note that since
> argv is an array of POINTERS to strings, the simple thing to do is to
> set up your own string and then store the address/pointer in argv[n].
> This avoids the potential pitfalls that John's method involves and gives
> you the option to store ANYTHING YOU WANT in the argument list.

The problem with this is that ps may not look at the pointers.  If the
pointers are looked at this fragment

	if (*argv[1] == '-')
		for (argv[1]++;*argv[1];argv[1]++)
			/* option processing here */

would trash the second argument.  You might want to try writing a program
that handles its flags this way and see what ps shows.

Please don't post your results.  I will summarize if the is enough response.

- John.

Disclaimer -
	No disclaimer.  Whatcha donna do, sue me?