📄 sflproc.c
字号:
out Std_out filename, or NULL
err Std_err filename, or NULL
preserveroot True if we're running as root now
</Table>
Returns 0 if the PROC_INFO block was correctly initialised; returns -1 if
there was an error opening one of the i/o streams. Before calling this
function you should have declared the PROC_INFO block using the syntax:
PROCESS_DATA myproc = PROCESS_DATA_INIT;
---------------------------------------------------------------------[>]-*/
int
process_setinfo (
PROCESS_DATA *procinfo,
const char *std_in, /* Stdin device, or NULL */
const char *std_out, /* Stdout device, or NULL */
Bool scratch_out, /* Scratch stdout file? */
const char *std_err, /* Stderr device, or NULL */
Bool scratch_err /* Scratch stderr file? */
)
{
const char
*spacepos,
*slashpos;
char
stdout_mode,
stderr_mode;
/* Figure out if it is permissable to search the path */
/* It's permissable if the filename to be run doesn't contain a slash */
/* of its own already. */
procinfo-> searchpath = FALSE;
if (procinfo-> filename)
{
spacepos = strchr (procinfo-> filename, ' ');
if (spacepos == NULL)
spacepos = procinfo-> filename + strlen (procinfo-> filename);
slashpos = strchr (procinfo-> filename, '/');
#if (defined (MSDOS_FILESYSTEM))
if (!slashpos)
slashpos = strchr (procinfo-> filename, '\\');
#endif
if (slashpos == NULL || slashpos > spacepos)
procinfo-> searchpath = TRUE;
}
/* Figure out if root privilege should be retained. If the real user */
/* is root and effective user is root, then we retain root privilege */
/* for the executed program. Otherwise we want to discard it (default) */
procinfo-> preserveroot = FALSE;
#if (defined (__UNIX__))
if (getuid () == 0 && geteuid () == 0)
procinfo-> preserveroot = TRUE;
#endif
/* Open the i/o streams if requested. Note that process_set_io
* returns NULL_HANDLE if the supplied filename is null or empty.
*/
stdout_mode = scratch_out? 'w': 'a';
stderr_mode = scratch_err? 'w': 'a';
procinfo-> in = process_open_io (std_in, 'r');
procinfo-> out = process_open_io (std_out, stdout_mode);
procinfo-> err = process_open_io (std_err, stderr_mode);
if (procinfo-> in == -1
|| procinfo-> out == -1
|| procinfo-> err == -1)
{
process_close_io (procinfo);
return (-1);
}
else
return (0);
}
/* ---------------------------------------------------------------------[<]-
Function: process_open_io
Synopsis: Opens a file for i/o and returns a handle ready for passing to
process_create_full(). The filename may be null or empty, in which case
this function returns -2, which indicates a null file handle. If there is
an error, it returns -1. Otherwise it returns a file handle >= 0.
---------------------------------------------------------------------[>]-*/
int
process_open_io (
const char *filename,
char access_type /* r, w, a */
)
{
int
handle,
mode = 0,
permissions = 0;
if (filename == NULL || *filename == '\0')
return (-2); /* Indicates a null handle */
#if (defined (__UNIX__) || defined (__OS2__))
mode = O_NOCTTY;
#endif
if (access_type == 'r')
{
mode += O_RDONLY;
permissions = 0;
}
else
if (access_type == 'w')
{
mode += O_WRONLY | O_CREAT | O_TRUNC;
permissions = S_IREAD | S_IWRITE;
}
else
if (access_type == 'a')
{
mode += O_WRONLY | O_CREAT | O_APPEND;
permissions = S_IREAD | S_IWRITE;
}
handle = open (filename, mode, permissions);
#if (defined (WIN32))
/* Under Windows, we need to move the file pointer to the end of the
* file ourselves, for append files, since for some reason this does
* not happen automatically for file handles passed to subprocesses.
*/
if (access_type == 'a')
lseek (handle, 0, SEEK_END);
#endif
#if (defined (DEBUG))
if (handle < 0)
perror ("Error opening redirection stream");
#endif
return (handle);
}
/* ---------------------------------------------------------------------[<]-
Function: process_close_io
Synopsis: Closes any file handles opened for the process. Use this
function after you're finished with a process_create_full() call.
---------------------------------------------------------------------[>]-*/
void
process_close_io (PROCESS_DATA *procinfo)
{
if (procinfo-> in >= 0)
{
close (procinfo-> in);
procinfo-> in = NULL_HANDLE;
}
if (procinfo-> out >= 0)
{
close (procinfo-> out);
procinfo-> out = NULL_HANDLE;
}
if (procinfo-> err >= 0)
{
close (procinfo-> err);
procinfo-> err = NULL_HANDLE;
}
}
/* ---------------------------------------------------------------------[<]-
Function: process_status
Synopsis: Returns status of process specified by process ID. Returns
one of these values, or -1 if there was an error:
<Table>
PROCESS_RUNNING Process is still running.
PROCESS_ENDED_OK Process ended normally.
PROCESS_ENDED_ERROR Process ended with an error status.
PROCESS_INTERRUPTED Process was interrupted (killed).
</Table>
In the case of PROCESS_ENDED_ERROR, the global variable process_errno is
set to the exit code returned by the process.
---------------------------------------------------------------------[>]-*/
int
process_status (
PROCESS process)
{
#if (defined (__UNIX__) || defined (__OS2__))
int
status;
pid_t
return_pid;
/* waitpid() returns 0 if the child process is still running, or the */
/* process id if it stopped. It can also return -1 in case of error. */
/* No other return value is possible. */
return_pid = waitpid (process, &status, WNOHANG | WUNTRACED);
if (return_pid == 0)
return (PROCESS_RUNNING);
else
if (return_pid == process)
{
if (WIFEXITED (status)) /* Program called exit() */
{
process_errno = WEXITSTATUS (status);
if (process_errno) /* Treat exit (0) as normal end */
return (PROCESS_ENDED_ERROR);
else
return (PROCESS_ENDED_OK);
}
else
if (WIFSIGNALED (status)) /* Process was interrupted */
return (PROCESS_INTERRUPTED);
else
return (PROCESS_ENDED_OK);
}
else
return (-1);
#elif (defined (WIN32))
DWORD
status;
ASSERT (process);
status = WaitForSingleObject (process-> process, 0);
if (status == WAIT_TIMEOUT)
return (PROCESS_RUNNING);
else
if (status == WAIT_OBJECT_0)
return (PROCESS_ENDED_OK);
else
if (status == WAIT_ABANDONED)
return (PROCESS_ENDED_ERROR);
else
return (-1);
#elif (defined (__VMS__))
ASSERT (process);
if (process-> status == 0)
return (PROCESS_RUNNING);
else
return (PROCESS_ENDED_OK);
#else
return (-1); /* Not supported on this system */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: process_kill
Synopsis: Ends a process specified by a process id. The current process
must have the appropriate authority to stop the specified process.
Returns zero if the process was killed, -1 if there was an error.
---------------------------------------------------------------------[>]-*/
int
process_kill (
PROCESS process)
{
#if (defined (__UNIX__) || defined (__OS2__))
int count = 5;
ASSERT (process);
/* First give it a chance to gracefully exit... */
kill (process, SIGTERM);
while (process_status (process) == PROCESS_RUNNING && count--)
sleep (1);
/* Then get brutal if neccessary. */
if (process_status (process) == PROCESS_RUNNING)
{
kill (process, SIGKILL);
while (process_status (process) == PROCESS_RUNNING)
sleep (1);
}
return (0);
#elif (defined (WIN32))
ASSERT (process);
TerminateProcess (process-> process, 1);
while (process_status (process) == PROCESS_RUNNING)
Sleep (100);
process_close (process);
return (0);
#elif (defined (__VMS__))
ASSERT (process);
sys$delprc (process-> id);
process_close (process);
return (0);
#else
return (-1); /* Not supported on this system */
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: process_close
Synopsis: You should call this function when a process has ended
normally, if you did not specify the wait option when calling the
process_create() function. On some systems, each created process
uses some memory. process_close() guarantees that this memory is
correctly freed. Does nothing if the process handle is NULL.
---------------------------------------------------------------------[>]-*/
void
process_close (
PROCESS process)
{
#if (defined (WIN32))
if (process)
{
mem_free (process-> envd);
mem_free (process);
}
#elif (defined (__VMS__))
mem_free (process);
#endif
}
/* ---------------------------------------------------------------------[<]-
Function: process_server
Synopsis: Converts the process from an interactive foreground process
into a background process. Depending on the system either the existing
process becomes a background process, or a new process is started as
a background process and the existing process terminates.
Requires the original command-line arguments as passed to the main()
function. If a new process is started, any arguments that match any
of the values in the (NULL terminated) 'sswitch' array will be omitted
from the arguments to the new process. You should specify the
command-line switch(es) your main program uses to run as a background
service. If it returns, returns 0 if okay, and returns -1 if there
was an error.
The precise effect of this function depends on the system. On UNIX,
does this:
<LIST>
Switches the process to run as a background job, under init;
closes all open files;
moves to a safe, known working directory, if required;
sets the umask for new files;
opens stdin, stdout, and stderr to the null device;
enforces exclusive execution through a lock file, if required;
logs the process id in the lock file;
ignores the hangup unwanted signals.
</LIST>
On OS/2, starts a new copy of the program up, detached, and running
separately from the current process, and if successful, the existing
process exits.
On other systems does nothing except return 0.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -