Thread: how to force a function to never return...like exec() does it

  1. #1
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136

    how to force a function to never return...like exec() does it

    how does exec() do it? on successful call of exec() family of functions, they never return...

    how to i emulate that.

    assume the standard example,

    Code:
    execl("/bin/ls","ls",NULL);
    now this would never return.

    i m trying to emulate exec()'s never to return feature...

    Code:
    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    
    void myexec(const char* path,const char* argv)
    {
        chdir(path);
        system(argv);
        sleep(2);    //make process orphan
        exit(100);   //exit to init
    }
    
    
    int main(int argc,char *argv[])
    {
        if(argc!=3)
        {
            printf("USAGE:%s <path> <command>\n",argv[0]);
            exit(1);
        }   
        if( fork() == 0)
        {
            myexec(argv[1],argv[2]);
        } 
        else
        { 
              sleep(1);   //suspend parent
              exit(0);      //be a bad parent ;) 
         }
        printf("this should never be executed");    
    }
    i m not trying anything fancy...only to emulate the "no return" feature once a command is executed.

    so when i run this program
    (trial 1)
    Code:
    [c_d@localhost cfiles]$ gcc 1.c
    [c_d@localhost cfiles]$ ./a.out /bin/ls ls
    1.c	  a.out		 fcopy.c~  frevread.c~	msg~	 prgm1.c~  prgm2.c~  prgm3.c~  prgm4.c~  prgm5.c~  prgm7.c     sth~
    1.c~	  cfiles.tar.7z  file1~    key.c	prgm1	 prgm2	   prgm3     prgm4     prgm5	 prgm6.c   prgm7.c~
    alpha.c~  f1~		 fread.c~  key.c~	prgm1.c  prgm2.c   prgm3.c   prgm4.c   prgm5.c	 prgm6.c~  printip.c~
    [c_d@localhost cfiles]$
    (trial 2)
    Code:
    [c_d@localhost cfiles]$ ./a.out /home/c_d/workspace/unix/shellscripts/ ./leapyear_prgm07.sh
    2009 is not a leap year
    [c_d@localhost cfiles]$


    i get what i want...the line "this should never be executed" never gets printed


    but i m not happy...i m unnecessarily wasting away 2 secs for emulating this...
    and i personally dont feel it as an elegant way to emulate exec()....

    please help me grasp the internals of exec() call... and explain to me how it works and tell me if there is an alternative to make a function-call never return...

    also please explain to me, why in execl*() a set of arguments is preferred to be passed as in
    Code:
    execl ("/bin/ls", "ls", "-l", (char *)0);
    when it could have been implemented as
    Code:
    execl ("/bin/ls", "ls -l", (char *)0);
    instead

    ...and i have same complaint with execv*() style exec()...

    thank you.
    Last edited by creeping death; 03-27-2009 at 12:35 PM.
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by creeping death View Post
    but i m not happy...i m unnecessarily wasting away 2 secs for emulating this...
    So don't sleep. I'm not sure what the problem is.

    and i personally dont feel it as an elegant way to emulate exec()....
    Why are you emulating it in the first place?

    please help me grasp the internals of exec() call... and explain to me how it works and tell me if there is an alternative to make a function-call never return...
    The fact that exec() never returns is as inevitable as death... If you replace the currently executing program with something else, obviously the old program no longer exists. Something can't return if it doesn't exist.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    ok...
    So don't sleep. I'm not sure what the problem is.
    now that you mention it...i feel quite stupid.

    but why in execl*() a set of arguments is preferred to be passed as in
    Code:
    execl ("/bin/ls", "ls", "-l", (char *)0);
    when it could have been implemented as
    Code:
    execl ("/bin/ls", "ls -l", (char *)0);
    instead
    Last edited by creeping death; 03-27-2009 at 12:56 PM.
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by creeping death View Post
    ok...

    now that you mention it...i feel quite stupid.

    but why in execl*() a set of arguments is preferred to be passed as in
    Code:
    execl ("/bin/ls", "ls", "-l", (char *)0);
    when it could have been implemented as
    Code:
    execl ("/bin/ls", "ls -l", (char *)0);
    instead
    There are a few reasons. One, exec() is a system call, which means the kernel does it. The single string will have to be broken back into individual arguments to pass in the argv[] array of the executed process anyway. It would be pointless to force the kernel to do that.

    Two, if you are dynamically building a command line, you would have to use sprintf() to pack the arguments into a single string -- again, why bother when you already have them separately.

    Three, what happens if you have a program that has a space in its name? There would be no way to distinguish "space as argument separator" from "space just because there happened to be a space in the name."
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Perhaps that stems from how the execl() family of functions has been declared as in:
    Code:
    int execl (const char *path, const char *arg0, ..., const char *argn, (char *)0);
    As you can see each command line argument is a parameter unto itself.

  6. #6
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    thanks but...where can i find the defination of the exec() family of funtions...

    unistd.h has the following...and they seem to be more like declarations than definations...

    Code:
    /* Replace the current process, executing PATH with arguments ARGV and
       environment ENVP.  ARGV and ENVP are terminated by NULL pointers.  */
    extern int execve (__const char *__path, char *__const __argv[],
    		   char *__const __envp[]) __THROW __nonnull ((1));
    
    #ifdef __USE_GNU
    /* Execute the file FD refers to, overlaying the running program image.
       ARGV and ENVP are passed to the new program, as for `execve'.  */
    extern int fexecve (int __fd, char *__const __argv[], char *__const __envp[])
         __THROW;
    #endif
    
    
    /* Execute PATH with arguments ARGV and environment from `environ'.  */
    extern int execv (__const char *__path, char *__const __argv[])
         __THROW __nonnull ((1));
    
    /* Execute PATH with all arguments after PATH until a NULL pointer,
       and the argument after that for environment.  */
    extern int execle (__const char *__path, __const char *__arg, ...)
         __THROW __nonnull ((1));
    
    /* Execute PATH with all arguments after PATH until
       a NULL pointer and environment from `environ'.  */
    extern int execl (__const char *__path, __const char *__arg, ...)
         __THROW __nonnull ((1));
    
    /* Execute FILE, searching in the `PATH' environment variable if it contains
       no slashes, with arguments ARGV and environment from `environ'.  */
    extern int execvp (__const char *__file, char *__const __argv[])
         __THROW __nonnull ((1));
    
    /* Execute FILE, searching in the `PATH' environment variable if
       it contains no slashes, with all arguments after FILE until a
       NULL pointer and environment from `environ'.  */
    extern int execlp (__const char *__file, __const char *__arg, ...)
         __THROW __nonnull ((1));
    thanks...
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by creeping death View Post
    thanks but...where can i find the defination of the exec() family of funtions...

    unistd.h has the following...and they seem to be more like declarations than definations...
    exec*() are System Calls. That means they are built into the Kernel.
    If you want to see how they work, download the Linux source code and take a look.
    Although there's no way to do the same thing as exec*() without going through the Kernel, since the OS won't let you do it.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  8. #8
    apprentiCe
    Join Date
    Oct 2008
    Location
    Hyderabad,India
    Posts
    136
    thanks
    Code:
    printf("%c%c%c%c%c%c%c",0x68,0x68^0xd,0x68|0x4,0x68|0x4,0x68|0xf,0x68^0x49,0x68^0x62);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  2. doubt in c parser coding
    By akshara.sinha in forum C Programming
    Replies: 4
    Last Post: 12-23-2007, 01:49 PM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM