LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-10-2005, 03:10 AM   #1
alaios
Senior Member
 
Registered: Jan 2003
Location: Aachen
Distribution: Opensuse 11.2 (nice and steady)
Posts: 2,203

Rep: Reputation: 45
change child name (c fork)


Hi i have some code for creating a process that runs to the background

pid=fork();
if (pid<0){
printf("Error creating child process ");
}
if (pid >0){
exit(0);
}
sid=setsid();
if (sid<0){
perror("Problem with the child process");
}


The problem is that when i execute my small programme
./3threads
then in the ps -aux
i can see an entry that includes
./3threads as the process name
Is it possible to change this? and if it is possible how?
 
Old 09-10-2005, 04:54 AM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    pid_t pid;

    pid = fork();
    if (pid < 0) {
        printf("Error creating child process ");
        exit(1);
    }
    if (pid > 0) {
        exit(0);
    }
    setsid();

    /* You can safely leave this part out, 
     * the error will never happen (in this case).
    if (sid < 0) {
        perror("Problem with the child process");
    }
    */

    /* Change the name as shown by "ps ax" */
    sprintf(argv[0], "Hi there! (was 3threads)");

    sleep(20); /* Time to inspect with: ps ax */
    return 0;
}
 
Old 09-10-2005, 05:11 AM   #3
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
Quote:
sprintf(argv[0], "Hi there! (was 3threads)");
Beware overwriting argv[0] will likely shift remaining arguments offset, and argv[1] content.
Not a big deal as you probably have processed your arguments before the fork, but if some of these need to be used after the fork, you should copy them to a safer area before it.
 
Old 09-10-2005, 08:10 AM   #4
eddiebaby1023
Member
 
Registered: May 2005
Posts: 378

Rep: Reputation: 33
Quote:
Beware overwriting argv[0] will likely shift remaining arguments offset, and argv[1] content.
I'd have thought this unlikely as argv is simply an array of pointers, not the pointed-to content, so replacing one pointer with another shouldn't affect the other pointers at all.
 
Old 09-10-2005, 08:42 AM   #5
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
You do not replace one pointer with another, you replace data pointed to by data being of a likely different size.

Actually I was wrong about the argument shift, but if you new argv[0] name is longer than the old one, argv[1] will be trashed, and possibly argv[2] and so on depending on how much of the environment you overwrite.
 
Old 09-10-2005, 02:52 PM   #6
eddiebaby1023
Member
 
Registered: May 2005
Posts: 378

Rep: Reputation: 33
Quote:
Originally posted by jlliagre
You do not replace one pointer with another, you replace data pointed to by data being of a likely different size.

Actually I was wrong about the argument shift, but if you new argv[0] name is longer than the old one, argv[1] will be trashed, and possibly argv[2] and so on depending on how much of the environment you overwrite.
Yes, you're right, you should assign the pointer to the string to argv[0] instead. You may run into scoping issues, of course.
 
Old 09-10-2005, 03:24 PM   #7
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
You cannot change argv[0], it is not a pointer.
 
Old 09-10-2005, 03:38 PM   #8
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Quote:
Originally posted by jlliagre
You cannot change argv[0], it is not a pointer.
That's not correct. argv is of type pointer-to-pointer-to-char and argv[0] is of type pointer-to-char.
Here's what the C standard says about changing the strings in the argv array of strings:


The parameters argc and argv and the strings pointed to by the argv
array shall be modifiable by the program, and retain their last-stored
values between program startup and program termination.

So changing the strings is ok, just don't try to write past the end. But modifying the actual pointers
invokes undefined behaviour.
 
Old 09-10-2005, 04:20 PM   #9
Matir
LQ Guru
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Debian, Arch
Posts: 8,507

Rep: Reputation: 128Reputation: 128
Code:
const char *name="newname";
argv[0]=name;
Will NOT work. It updates the local copy of argv, not the one being used by the system. In other words, the system has its own copy of argv that you must update. So the new name of the executable must be no longer than the old one.
 
Old 09-11-2005, 08:34 AM   #10
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
So the new name of the executable must be no longer than the old one.
Not correct. The buffer size for argv[0] is fixed, as defined in /usr/include/bits/posix1_lim.h. On debian sarge (and most other posix OS's) it is:
Code:
#define _POSIX_PATH_MAX 256
So, no need (nor possible) to get a new pointer for argv[0]. If you keep it within 256, no shifting/overwriting/thrashing of argv[1] , argv[2],... argv[n], nor segfaults will occur either.

Just stay within 255 bytes (leave 1 byte room for '\0') and you can write whatever you want in the buffer pointed to by argv[0].

Last edited by Hko; 09-11-2005 at 08:46 AM.
 
Old 09-11-2005, 08:50 AM   #11
alaios
Senior Member
 
Registered: Jan 2003
Location: Aachen
Distribution: Opensuse 11.2 (nice and steady)
Posts: 2,203

Original Poster
Rep: Reputation: 45
COOLL >> Where have u learned all these things HKO?
 
Old 09-11-2005, 10:08 AM   #12
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789

Rep: Reputation: 492Reputation: 492Reputation: 492Reputation: 492Reputation: 492
This is perhaps cool, but wrong ...

A maximum size defined somewhere doesn't imply a fixed size is used.
 
Old 09-11-2005, 11:53 AM   #13
Matir
LQ Guru
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Debian, Arch
Posts: 8,507

Rep: Reputation: 128Reputation: 128
In fact, a fixed size is most certainly not used. I wrote a bit of code to dump the pointers of argv.
Code:
#include <stdio.h>

int main(int argc,char **argv){
        int i;

        for(i=0;i<argc;i++)
                printf("argv[%d]: 0x%08x\n",i,argv[i]);

        return 0;
}
Running said code produces:
Code:
$ ./argv_size hello world
argv[0]: 0xbfc0929e
argv[1]: 0xbfc092aa
argv[2]: 0xbfc092b0
The first two numbers are only 12 bytes apart. So, writing more than 12 bytes into argv[0] would overflow into argv[1].
 
Old 09-11-2005, 04:34 PM   #14
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally posted by jlliagre
This is perhaps cool, but wrong ...
A maximum size defined somewhere doesn't imply a fixed size is used.
Hmm... It appears that you're right.
I've read about this while ago on usenet (comp.unix.programmer). Now I've actually tried it, and it's quite clear that it's wrong:.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int i;

    /* Change the name as shown by "ps ax" to "abcdef...zabcdef...". */
    for (i = 0; i < 22; ++i) {
        argv[0][i] = (i % 26) + 'a';
    }
    argv[0][i] = '\0';  /* terminate string */
    sleep(20);  /* Time to inspect with: ps ax */
    return 0;
}
Run:
Code:
bash$ ./argvchange 111 222 333 444 &
bash$ ps ax | fgrep abcd
5881 pts/2    S      0:00 abcdefghijklmnopqrstuv 33 444
Sorry.

Last edited by Hko; 09-11-2005 at 04:36 PM.
 
Old 09-11-2005, 04:41 PM   #15
Matir
LQ Guru
 
Registered: Nov 2004
Location: San Jose, CA
Distribution: Debian, Arch
Posts: 8,507

Rep: Reputation: 128Reputation: 128
No need to be sorry, Hko. LQ is about learning, last I checked. And you made people think more carefully about all this.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to change environment variables of a parent envrionment from a child one. pulsez Linux - Software 1 11-09-2005 06:24 AM
GCC fork() - Can a child change a parent variable? johnhardey Programming 4 03-10-2005 10:49 AM
why there're lots of child processes when fork? iclinux Programming 3 01-18-2005 07:09 AM
Getting a parent to communicate with its child -- fork() kamel Programming 3 06-02-2004 03:04 AM
child-parent-&-fork mukul Programming 2 03-24-2001 01:12 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:13 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration