Solved

exec(2) commands returning  to calling program

Posted on 1998-10-07
13
293 Views
Last Modified: 2013-12-27
Alright we have multi threaded program that used to
use System calls but appearently the system command
is not thread safe (anymore).  Sun tech support offer
the advice that we should use exec commands instead which
is fine but I cannot get the perl script (or any other script) to return to the calling code.  (see below)
so I can see the debug statment before execvp but not the
printf statement afterwards.  If I can't make the call
this way how can I make the call?

#include "ToolLib.h"
#include <stdlib.h>
#include <libgen.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#define ONE_DAY 1 * 24 * 60 * 60              /* day * hours/day * min/hour * sec/min = 86400 */
#define SECTION_TITLE_MARKER    '['
#define COMMENT_MARKER          ';'
#define EMPTY_LINE              '\0'

mutex_t gSystemCallMutex;

int main(int argc, char** argv)
{
    char          gLogDir[DIR_SZ];
    bool          gbDebug;
    char          cmd[CMD_SZ];
    gbDebug = TRUE;
    sprintf(gLogDir, "/home/xx4525/c++/dev/SafeBuild/tgt/unix/log/build/%s");
    sprintf(cmd, "mkdir -p %s ; chmod 777 %s", gLogDir, gLogDir);
    return MakeSystemCall(gbDebug, cmd);
}

extern bool MakeSystemCall(bool bDebug, char* pFullCmd)
{
    int     rc;
    pid_t   pid;
    int     i;
    int     arg_list_length;
    char    *FullPath;
    char    System_Call_Path[256];
    char    *Ptr;

    char    msg[256];
    char    *arg_list[16];
 
    char    Path_To_System_Call[] = "/home/xx4525/perl/dev/";
    char    System_Call_Script[]  = "Plague";


    pid = fork1();

    if (bDebug == TRUE) { printf("\n\tCOMMAND: %s\n\n",pFullCmd ); }
    if(mutex_lock(&gSystemCallMutex) != 0)
    {
        perror("MakeSystemCall");
        return (FALSE);
    }

    strcpy(System_Call_Path,Path_To_System_Call);
    strcat(System_Call_Path,System_Call_Script);

    if (bDebug == TRUE) { printf("\n\tSYSTEM SCRIPT: %s\n\n",System_Call_Path ); }

    if ( pid <= -1)
    {
        perror(pFullCmd);
    }
    else
    {
        arg_list[1] = strtok(pFullCmd, " ");
        for(i = 2; (arg_list[i] = strtok(NULL, " ")) != NULL; i++);
        arg_list[i] = NULL;

        if (bDebug == TRUE)
        {
            for(i = 1; arg_list[i] != NULL; i++) { fprintf(stdout, "*** CURRENT COMMAND %d: [%s] ***\n",i, arg_list[i]); }
            fflush(stdout);
        }
        rc = execvp(System_Call_Path, arg_list);

        sprintf(msg, "\n\n Don't Thread on me - Cmd: %s\n\n", pFullCmd);
        fprintf( stdout, "%s",msg );
        _exit(1);
    }

    if(mutex_unlock(&gSystemCallMutex) != 0)
    {
        perror("MakeSystemCall");
        return(FALSE);
    }
 
    return (rc == 0) ? TRUE : FALSE;
}
0
Comment
Question by:xx4525
  • 5
  • 4
  • 3
  • +1
13 Comments
 

Author Comment

by:xx4525
ID: 2007288
Edited text of question
0
 

Author Comment

by:xx4525
ID: 2007289
Edited text of question
0
 
LVL 3

Accepted Solution

by:
arunm earned 100 total points
ID: 2007290
If a program sucessfully execs, the address space is modifed so there is nothing to return to. The printf will only be reached if the exec fails.
 
0
 
LVL 3

Expert Comment

by:arunm
ID: 2007291
Also you dont appear to be distinguishing between the 2 threads in your program. Is this intentional?
0
 
LVL 84

Expert Comment

by:ozo
ID: 2007292
You may want to fork then exec
0
 
LVL 3

Expert Comment

by:elfie
ID: 2007293
Some more clarification about ozo's comment.

a fork call will duplicate your process into two (almost) identical processes. Then in one of both (normally) the program which get a zero return form the fork call, you will executed the  exec call to replace to current running code with your ocde of choice.
The other process will receive a non-zero return from fork (meaning the son's process id).

As what the system command is , the normal implmentation is first a fork call followed by some form of exec call.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:xx4525
ID: 2007294
Thank you all for your help but I am afraid that I am
going to need some clarification.

Alright I can understand why the printf is not executing but
I should be executing the execvp inside the forked process,
right?  Thus the parent process should complete the execution
after the child is toast or I am executing the execvp on both
the child and the parent?

What do you mean by "distinguishing between the 2 threads"?
0
 
LVL 3

Expert Comment

by:arunm
ID: 2007295
After the fork, if the pid = 0, its the child. If the pid > 0 its the parent , a -ve pid indicates a failure. So both your processes are exec-ing.
 
0
 
LVL 3

Expert Comment

by:elfie
ID: 2007296
some sample code for using fork/exec to execute a shell script

  argv[0] = argv0;
  argv[1] = script_file;
  argv[2] = NULL;

#ifdef PROTO_OS2
  script_pid = _spawnvp(P_NOWAIT, "cmd.exe", argv);
  if (script_pid == -1)
    Error("Execvp failed: %s\n",strerror(own_errno()));
#else
  fork_code = fork();
  switch (fork_code)
    {
    case -1:
      Error("Fork failed: %s\n", strerror(own_errno()));
      exit(EXITCODE_LAUNCH_ERROR);

    case 0:             /* the son process */
      close_anything_thats_open();
      setsid();
      Error("Starting background script %s",script_file);
      exec_code = execvp("sh", argv);
      if (exec_code == -1)
      Error("Execvp failed: %s\n", strerror(own_errno()));
      exit(0);/*no EXITCODE necessary here - different process*/
    default:   /* the father must wait until the son is there */
      script_pid = fork_code;      /* to kill afterwards */
    }
#endif /* PROTO_OS2 */
#endif /* MSC32 */
0
 

Author Comment

by:xx4525
ID: 2007297
Happiness is truely mine I have some more questions but
I think I have a start.  But the questions are for
my knowledge

What do setsid() do for me?  Is is necessary?

I am assuming that close_anything_thats_open() is a user defined
function but what am I looking to close?

Finally I hope
default:   /* the father must wait until the son is there */
             script_pid = fork_code; /* to kill afterwards */
           }
What is the perpose of this commparison and will this work as
well?
            default:
                    waitpid(pid, &rc, 0);
                    break;
    }

0
 
LVL 3

Expert Comment

by:arunm
ID: 2007298
Whenever you fork a process, as the child is and exact copy of the parent they will both share items such as file pointers. To avoid a confusion and to aid clairity it is best to close anything that is left open.  Wait is essentially used to syncronise processes, so you can confirm that the child process has finished before continuing with the parent. setsid() is used to process and session group id. In this case it is not mandatory.
 
 
0
 
LVL 3

Expert Comment

by:elfie
ID: 2007299
setsid() combined with closing stdin/out/err is use dto detach from curent running terminal. it is only needed to make a real deamon process that, after completely started, will show pid 1 as it's parent process. It also prevents that the process will be killed automatically when a user who started it will logoff. (in your case not needed, but i did a cut/paste from some existing code.

The same for close_anything ... Since your starting another program you (probably) don't need any open file from the orignating program. Since Fork duplicates the process, it also duplicates all open filedescriptors, and keeping them open (even when not needed).

The saving of the son's id , is that the parent process will write this id into a file, so later we can do a kill `cat file` to kill the deamon process.

Basically the example is bit to extended, but it shows you the basics of how fork/exec can be used.
0
 

Author Comment

by:xx4525
ID: 2007300
Cool Thanks all

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Attention: This article will no longer be maintained. If you have any questions, please feel free to mail me. jgh@FreeBSD.org Please see http://www.freebsd.org/doc/en_US.ISO8859-1/articles/freebsd-update-server/ for the updated article. It is avail…
Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now