487 lines
18 KiB
HTML
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>
|
|
Syntax<br>
|
|
<pre>
|
|
#include <spawn.h>
|
|
#include <qlg.h>
|
|
|
|
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>
|
|
Service Program Name: QP0ZSPWN<br>
|
|
<!-- iddvc RMBR -->
|
|
<br>
|
|
Default Public Authority: *USE<br>
|
|
<!-- iddvc RMBR -->
|
|
<br>
|
|
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 <<strong>qlg.h</strong>> 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 <errno.h>
|
|
#include <fcntl.h>
|
|
#include <spawn.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <qlg.h>
|
|
#include <Qp0lstdi.h>
|
|
|
|
#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 >= 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(&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 *)&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(&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, &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(&spw_inherit,0x00,sizeof(spw_inherit));
|
|
spw_envp[0] = NULL;
|
|
spw_child_pid = QlgSpawn((Qlg_Path_Name_T *)&spw_path,
|
|
spw_fd_count, NULL, &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 *)&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,&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 *)&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 *)&f_path_name, O_RDONLY);
|
|
if (fd_read == -1)
|
|
{
|
|
printf("FAILURE: open() for read with errno = %d\n",errno);
|
|
QlgUnlink((Qlg_Path_Name_T *)&f_path_name);
|
|
return -1;
|
|
}
|
|
|
|
/* Verify what child wrote. */
|
|
rc = read(fd_read, &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, &buf_int, sizeof(int));
|
|
if ( (rc != sizeof(int)) || (buf_int != pid) )
|
|
printf("FAILURE: read() child getppid()\n");
|
|
rc = read(fd_read, &buf_int, sizeof(int));
|
|
if ( (rc != sizeof(int)) || (buf_int != pgrp) )
|
|
printf("FAILURE: read() child getpgrp()\n");
|
|
rc = read(fd_read, &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, &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 *)&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 <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
/* 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, &ppid, sizeof(pid_t));
|
|
if (rc != sizeof(pid_t))
|
|
return 72;
|
|
rc = write(fd, &pgrp, sizeof(pid_t));
|
|
if (rc != sizeof(pid_t))
|
|
return 73;
|
|
rc = write(fd, &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>
|
|
|