//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/7999585e-fdab-4e7b-b86c-67d55e862138/ProcXe.c

//Warning: This code has been marked up for HTML

/***************************************************************************
$name: ProcXe.c 
$version: 1.0 
$date_modified: 120702 
$description: Demonstrates creating and waiting on a child process.
$owner: Ulrich Neumann, Germany
Copyright (c) 2002 Novell, Inc. All Rights Reserved.

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
CUSTOMERS WITH RESPECT TO THIS CODE.
****************************************************************************/
/*
** Notes: Make sure that your nlm is marked multiple! Make sure that your
** NLM is called: proctest.nlm or you change the line where procve loads the
** binary (itself) as the new process.
*/
#include <proc.h>
#include <stdio.h>
#include <screen.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <nksapi.h>
#include <sys/wait.h>


void main
(
   int   argc,
   char   *argv[]
)
{
   int         in[2], out[2], err[2], len, status;
   char         *cstring, *pstring, buf[200];
   const char   *args[3];
   pid_t         pid;
   wiring_t      wire;

   cstring = "If this can be read the child is talking to the parent\n";
   pstring = "If this can be read the parent is talking to the child\n";

/*
** So that the screen isn't discarded at the end until you've had a chance
** to see the results.
*/
   setscreenmode(0);

   args[0] = cstring;
   args[1] = cstring;
   args[2] = (char *) NULL;

   len = strlen(cstring) + 1;

   if (argv[1] && !strcmp(argv[1], cstring))
   {
      // child part...

      printf("%s", cstring);
      fwrite("", 1, 1, stdout);         // send something via stdout to parent

      fgets(buf, len, stdin);
      fread(&buf[len-1], 1, 1, stdin);   // read something from parent

      cprintf("%s", buf);
      sleep(2);                        // wait to see waitpid functional

      exit(1);
   }
   else
   {
      // parent part...

      pipe(in);
      pipe(out);
      pipe(err);

      // wire stdin, stdout and stderr between parent and child...

      wire.infd  = in [0];
      wire.outfd = out[1];
      wire.errfd = err[1];

      pid = procve("proctest.nlm", PROC_CURRENT_SPACE, NULL, &wire, NULL,
                                                   NULL, NULL, NULL, args);

      // close sides of the pipe unneeded in parent...

      close(in[0]);
      close(out[1]);
      close(err[1]);

      if (read(out[0], buf, len))      // read something from child

         printf(buf);

      write(in[1], pstring, len);      // write something to child


      close(in[1]);
      close(out[0]);
      close(err[0]);
   }

/*
** Wait for the child to terminate and print the status. The status is
** reported via exit() in the child.
*/
   waitpid(0, &status, WNOHANG);
   printf("Wait on pid: %d returns status: %04X\n", pid, status);

   exit(0);
}