ibm-information-center/dist/eclipse/plugins/i5OS.ic.apis_5.4.0.1/spawnu.htm

487 lines
18 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Copyright" content="Copyright (c) 2006 by IBM Corporation">
<title>QlgSpawn()--Spawn Process (using NLS-enabled path name)</title>
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<!-- Begin Header Records -->
<!-- Created for V5R1-->
<!-- Edited by Kersten Feb 02 -->
<!-- This file has undergone html cleanup July 2002 by JET -->
<!-- End Header Records -->
<link rel="stylesheet" type="text/css" href="../rzahg/ic.css">
</head>
<body>
<a name="Top_Of_Page"></a>
<!--Java sync-link-->
<script type="text/javascript" language="Javascript" src="../rzahg/synch.js">
</script>
<h2>QlgSpawn()--Spawn Process (using NLS-enabled path name)</h2>
<div class="box" style="width: 60%;">
<br>
&nbsp;&nbsp;Syntax<br>
<pre>
#include &lt;spawn.h&gt;
#include &lt;qlg.h&gt;
pid_t QlgSpawn(const Qlg_Path_Name_T <em>*path</em>,
const int <em>fd_count</em>,
const int <em>fd_map[]</em>,
const struct inheritance <em>*inherit</em>,
char * const <em>argv[]</em>,
char * const <em>envp[]</em>);
</pre>
<br>
&nbsp;&nbsp;Service Program Name: QP0ZSPWN<br>
<!-- iddvc RMBR -->
<br>
&nbsp;&nbsp;Default Public Authority: *USE<br>
<!-- iddvc RMBR -->
<br>
&nbsp;&nbsp;Threadsafe: Conditional; see <a href="#USGNOTES">Usage
Notes</a>.<br>
<!-- iddvc RMBR -->
<br>
</div>
<p>The <strong>QlgSpawn()</strong> function, like the <strong>spawn()</strong>
function, creates a child process that inherits specific attributes from the
parent. The difference is that for the <em>path</em> parameter, the
<strong>QlgSpawn()</strong> function takes a pointer to a Qlg_Path_Name_T
structure, while the <strong>spawn()</strong> function takes a pointer to a
character string in the CCSID of the job.</p>
<p>Limited information on the <em>path</em> parameter is provided here. For
more information on the <em>path</em> parameter and for a discussion of other
parameters, authorities required, and return values, see <a href=
"spawn.htm">spawn()</a>--Spawn Process.</p>
<br>
<h3>Parameters</h3>
<dl>
<dt><strong><em>path</em></strong></dt>
<dd>(Input) A pointer to a Qlg_Path_Name_T structure that contains a specific
path name or a pointer to a specific path name of an executable file that will
run in the new (child) process. For more information on the Qlg_Path_Name_T
structure, see <a href="../apiref/pns.htm">Path name format</a>.</dd>
</dl>
<br>
<h3><a name="USGNOTES">Usage Notes</a></h3>
<p>See <a href="spawn.htm">spawn()</a>--Spawn Process for a complete discussion
of usage information for <strong>QlgSpawn()</strong>. In addition, the
following should be noted specifically for <strong>QlgSpawn()</strong>.</p>
<ol>
<li>Shell scripts are supported; however, the interpreter path in the shell
script itself cannot be a Qlg_Path_Name_T structure.</li>
</ol>
<br>
<h3>Related Information</h3>
<ul>
<li>The &lt;<strong>qlg.h</strong>&gt; file (see <a href="unix13.htm">Header
Files for UNIX-Type Functions</a>)<br>
<br>
</li>
<li><a href="spawn.htm">spawn()</a>--Spawn Process<br>
<br>
</li>
<li><a href="spawnpu.htm">QlgSpawnp()</a>--Spawn Process with Path (using
NLS-enabled file name)</li>
</ul>
<br>
<h3><a name="spawnuexmp">Example</a></h3>
<p>See <a href="../apiref/aboutapis.htm#codedisclaimer">Code disclaimer information</a>
for information pertaining to code examples.</p>
<strong>Parent Program</strong>
<p>The following ILE C for i5/OS program can be created in any library. This
parent program assumes the corresponding child program will be created with the
name CHILD in the library QGPL. Call this parent program with no parameters to
run the example.</p>
<pre>
/*****************************************************************/
/*****************************************************************/
/* */
/* FUNCTION: This program acts as a parent to a child program. */
/* */
/* LANGUAGE: ILE C for i5/OS */
/* */
/* APIs USED: QlgSpawn(), waitpid(), */
/* QlgCreat(), QlgUnlink(), QlgOpen() */
/* */
/*****************************************************************/
/*****************************************************************/
#include &lt;errno.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;spawn.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;unistd.h&gt;
#include &lt;qlg.h&gt;
#include &lt;Qp0lstdi.h&gt;
#define ARGV_NUM 6
#define ENVP_NUM 1
#define CHILD_PGM "QGPL/CHILD"
#define spwpath "/QSYS.LIB/QGPL.LIB/CHILD.PGM"
#define fpath "A_File"
typedef struct pnstruct
{
Qlg_Path_Name_T qlg_struct;
char pn[100]; /* This size must be &gt;= the path */
/* name length or this must be a */
/* pointer to the path name. */
};
/* This is a parent program that will use QlgSpawn() to start a */
/* child. A file is created that is written to, both by the parent */
/* and the child. The end result of the file will look something */
/* like the following: */
/* Parent writes Child writes */
/* ------------- --------------------------------------- */
/* 1 argv[0] getppid() getpgrp() getpid() */
/* The parent uses waitpid() to wait for the child to return and to */
/* retrieve the resulting status of the child when it does return. */
int main(int argc, char *argv[])
{
int rc; /* API return code */
int fd, fd_read; /* parent file descriptors */
char fd_str[4]; /* file descriptor string */
const char US_const[3]= "US";
const char Language_const[4]="ENU";
const char Path_Name_Del_const[2]= "/";
struct pnstruct f_path_name; /* file pathname */
int buf_int; /* write(), read() buffer */
char buf_pgm_name[22]; /* read() program name buffer */
struct pnstruct spw_path; /* QlgSpawn() *path */
int spw_fd_count = 0; /* QlgSpawn() fd_count */
struct inheritance spw_inherit; /* QlgSpawn() *inherit */
char *spw_argv[ARGV_NUM]; /* QlgSpawn() *argv[] */
char *spw_envp[ENVP_NUM]; /* QlgSpawn() *envp[] */
int seq_num; /* sequence number */
char seq_num_str[4]; /* sequence number string */
pid_t pid; /* parent pid */
char pid_str[11]; /* parent pid string */
pid_t pgrp; /* parent process group */
char pgrp_str[11]; /* parent process group string */
pid_t spw_child_pid; /* QlgSpawn() child pid */
pid_t wt_child_pid; /* waitpid() child pid */
int wt_stat_loc; /* waitpid() *stat_loc */
int wt_pid_opt = 0; /* waitpid() option */
/* Get the pid and pgrp for the parent. */
pid = getpid();
pgrp = getpgrp();
/* Format the pid and pgrp value into null-terminated strings. */
sprintf(pid_str, "%d", pid);
sprintf(pgrp_str, "%d", pgrp);
/* Initialize Qlg_Path_Name_T parameters */
memset(&amp;f_path_name,0x00,sizeof(struct pnstruct));
f_path_name.qlg_struct.CCSID = 37;
memcpy(f_path_name.qlg_struct.Country_ID,US_const,2);
memcpy(f_path_name.qlg_struct.Language_ID,Language_const,3);
f_path_name.qlg_struct.Path_Type = QLG_CHAR_SINGLE;
f_path_name.qlg_struct.Path_Length = sizeof(fpath)-1;
memcpy(f_path_name.qlg_struct.Path_Name_Delimiter,
Path_Name_Del_const,1);
memcpy(f_path_name.pn,fpath,sizeof(fpath)-1);
/* Create a file and maintain the file descriptor. */
fd = QlgCreat((Qlg_Path_Name_T *)&amp;f_path_name, S_IRWXU);
if (fd == -1)
{
printf("FAILURE: QlgCreat() with errno = %d\n",errno);
return -1;
}
/* Format the file descriptor into null-terminated string. */
sprintf(fd_str, "%d", fd);
/* Initialize Qlg_Path_Name_T parameters */
memset(&amp;spw_path,0x00,sizeof(struct pnstruct));
spw_path.qlg_struct.CCSID = 37;
memcpy(spw_path.qlg_struct.Country_ID,US_const,2);
memcpy(spw_path.qlg_struct.Language_ID,Language_const,3);
spw_path.qlg_struct.Path_Type = QLG_CHAR_SINGLE;
spw_path.qlg_struct.Path_Length = sizeof(spwpath)-1;
memcpy(spw_path.qlg_struct.Path_Name_Delimiter,
Path_Name_Del_const,1);
memcpy(spw_path.pn,spwpath,sizeof(spwpath)-1);
/* Write a '1' out to the file. */
seq_num = 1;
sprintf(seq_num_str, "%d", seq_num);
buf_int = seq_num;
write(fd, &amp;buf_int, sizeof(int));
/* Set the QlgSpawn() child arguments for the child. */
/* NOTE: The child will always get argv[0] in the */
/* LIBRARY/PROGRAM notation, but the QlgSpawn() argv[0] */
/* (spw_argv[0] in this case) must be non-NULL in order */
/* to allow additional arguments. For this example, the */
/* CHILD_PGM was chosen. */
/* NOTE: The parent pid and the parent process group are */
/* passed to the child for demonstration purposes only. */
spw_argv[0] = CHILD_PGM;
spw_argv[1] = pid_str;
spw_argv[2] = pgrp_str;
spw_argv[3] = seq_num_str;
spw_argv[4] = fd_str;
spw_argv[5] = NULL;
/* This QlgSpawn() will use simple inheritance for file */
/* descriptors (fd_map[] value is NULL). */
memset(&amp;spw_inherit,0x00,sizeof(spw_inherit));
spw_envp[0] = NULL;
spw_child_pid = QlgSpawn((Qlg_Path_Name_T *)&amp;spw_path,
spw_fd_count, NULL, &amp;spw_inherit, spw_argv, spw_envp);
if (spw_child_pid == -1)
{
printf("FAILURE: QlgSpawn() with errno = %d\n",errno);
close(fd);
QlgUnlink((Qlg_Path_Name_T *)&amp;f_path_name);
return -1;
}
/* The parent no longer needs to use the file descriptor, so */
/* it can close it, now that it has issued QlgSpawn(). */
rc = close(fd);
if (rc != 0)
printf("FAILURE: close(fd) with errno = %d\n",errno);
/* NOTE: The parent can continue processing while the child is */
/* also processing. In this example, though, the parent will */
/* simply wait until the child finishes processing. */
/* Issue waitpid() in order to wait for the child to return. */
wt_child_pid = waitpid(spw_child_pid,&amp;wt_stat_loc,wt_pid_opt);
if (wt_child_pid == -1)
{
printf("FAILURE: waitpid() with errno = %d\n",errno);
close(fd);
QlgUnlink((Qlg_Path_Name_T *)&amp;f_path_name);
return -1;
}
/* Check to ensure the child did not encounter an error */
/* condition. */
if (WIFEXITED(wt_stat_loc))
{
if (WEXITSTATUS(wt_stat_loc) != 1)
printf("FAILURE: waitpid() exit status = %d\n",
WEXITSTATUS(wt_stat_loc));
}
else
printf("FAILURE: unknown child status\n");
/* Open the file for read to verify what the child wrote. */
fd_read = QlgOpen((Qlg_Path_Name_T *)&amp;f_path_name, O_RDONLY);
if (fd_read == -1)
{
printf("FAILURE: open() for read with errno = %d\n",errno);
QlgUnlink((Qlg_Path_Name_T *)&amp;f_path_name);
return -1;
}
/* Verify what child wrote. */
rc = read(fd_read, &amp;buf_int, sizeof(int));
if ( (rc != sizeof(int)) || (buf_int != 1) )
printf("FAILURE: read()\n");
memset(buf_pgm_name,0x00,sizeof(buf_pgm_name));
rc = read(fd_read, buf_pgm_name, strlen(CHILD_PGM));
if ( (rc != strlen(CHILD_PGM)) ||
(strcmp(buf_pgm_name,CHILD_PGM) != 0) )
printf("FAILURE: read() child argv[0]\n");
rc = read(fd_read, &amp;buf_int, sizeof(int));
if ( (rc != sizeof(int)) || (buf_int != pid) )
printf("FAILURE: read() child getppid()\n");
rc = read(fd_read, &amp;buf_int, sizeof(int));
if ( (rc != sizeof(int)) || (buf_int != pgrp) )
printf("FAILURE: read() child getpgrp()\n");
rc = read(fd_read, &amp;buf_int, sizeof(int));
if ( (rc != sizeof(int)) || (buf_int != spw_child_pid) ||
(buf_int != wt_child_pid) )
printf("FAILURE: read() child getpid()\n");
/* Attempt one more read() to ensure there is no more data. */
rc = read(fd_read, &amp;buf_int, sizeof(int));
if (rc != 0)
printf("FAILURE: read() past end of data\n");
/* The parent no longer needs to use the read() file descriptor, */
/* so it can close it. */
rc = close(fd_read);
if (rc != 0)
printf("FAILURE: close(fd_read) with errno = %d\n",errno);
/* Clean up by performing unlink(). */
rc = QlgUnlink((Qlg_Path_Name_T *)&amp;f_path_name);
if (rc != 0)
{
printf("FAILURE: QlgUnlink() with errno = %d\n",errno);
return -1;
}
printf("completed successfully\n");
return 0;
}
</pre>
<br>
<br>
<br>
<strong>Child Program</strong>
<p>The following ILE C for i5/OS program must be created with the name CHILD
in the library QGPL in order to be found by the parent program. This program is
not to be called directly, as it is run through the use of QlgSpawn() in the
parent program.</p>
<pre>
/*******************************************************************/
/*******************************************************************/
/* */
/* FUNCTION: This program acts as a child to a parent program. */
/* */
/* LANGUAGE: ILE C for i5/OS */
/* */
/* APIs USED: getpid(), getppid(), getpgrp() */
/* */
/*******************************************************************/
/*******************************************************************/
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;unistd.h&gt;
/* This is a child program that gets control from a parent program */
/* that issues QlgSpawn(). This particular child program expects */
/* the following 5 arguments (all are null-terminated strings): */
/* argv[0] - child program name */
/* argv[1] - parent pid (for demonstration only) */
/* argv[2] - parent process group (for demonstration only) */
/* argv[3] - sequence number */
/* argv[4] - parent file descriptor */
/* If the child program encounters an error, it returns with a */
/* value greater than 50. If the parent uses wait() or waitpid(), */
/* this return value can be interrogated using the WIFEXITED and */
/* WEXITSTATUS macros on the resulting wait() or waitpid() */
/* *stat_loc field. */
int main(int argc, char *argv[])
{
pid_t p_pid; /* parent pid argv[1] */
pid_t p_pgrp; /* parent process group argv[2] */
int seq_num; /* parent sequence num argv[3] */
int fd; /* parent file desc argv[4] */
int rc; /* API return code */
pid_t pid; /* getpid() - child pid */
pid_t ppid; /* getppid() - parent pid */
pid_t pgrp; /* getpgrp() - process group */
/* Get the pid, ppid, and pgrp for the child. */
pid = getpid();
ppid = getppid();
pgrp = getpgrp();
/* Verify 5 parameters were passed to the child. */
if (argc != 5)
return 60;
/* Since the parameters passed to the child using QlgSpawn() are */
/* pointers to strings, convert the parent pid, parent process */
/* group, sequence number, and the file descriptor from strings */
/* to integers. */
p_pid = atoi(argv[1]);
p_pgrp = atoi(argv[2]);
seq_num = atoi(argv[3]);
fd = atoi(argv[4]);
/* Verify the getpid() value of the parent is the same as the */
/* getppid() value of the child. */
if (p_pid != ppid)
return 61;
/* If the sequence number is 1, simple inheritance was used in */
/* this case. First, verify the getpgrp() value of the parent */
/* is the same as the getpgrp() value of the child. Next, the */
/* child will use the file descriptor passed in to write the */
/* child's values for argv[0], getppid(), getpgrp(), */
/* and getpid(). Finally, the child returns, which will satisfy */
/* the parent's wait() or waitpid(). */
if (seq_num == 1)
{
if (p_pgrp != pgrp)
return 70;
rc = write(fd, argv[0], strlen(argv[0]));
if (rc != strlen(argv[0]))
return 71;
rc = write(fd, &amp;ppid, sizeof(pid_t));
if (rc != sizeof(pid_t))
return 72;
rc = write(fd, &amp;pgrp, sizeof(pid_t));
if (rc != sizeof(pid_t))
return 73;
rc = write(fd, &amp;pid, sizeof(pid_t));
if (rc != sizeof(pid_t))
return 74;
return seq_num;
}
/* If the sequence number is an unexpected value, return */
/* indicating an error. */
else
return 99;
}
</pre>
<br>
<hr>
API introduced: V5R1
<hr>
<center>
<table cellpadding="2" cellspacing="2" width="600">
<tr align="center">
<td valign="middle" align="center"><a href="#Top_Of_Page">Top</a> | <a href=
"unix11.htm">Process-Related APIs</a> | <a href="aplist.htm">APIs by
category</a> </td>
</tr>
</table>
</center>
</body>
</html>