process.zc
来自「实现树形结构」· ZC 代码 · 共 322 行
ZC
322 行
//[c]
//[of]:license
//[c] Code Browser - a folding text editor for programmers
//[c] Copyright (C) 2003-07 Marc Kerbiquet
//[c]
//[c] This program is free software; you can redistribute it and/or modify
//[c] it under the terms of the GNU General Public License as published by
//[c] the Free Software Foundation; either version 2 of the License, or
//[c] (at your option) any later version.
//[c]
//[c] This program is distributed in the hope that it will be useful,
//[c] but WITHOUT ANY WARRANTY; without even the implied warranty of
//[c] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//[c] GNU General Public License for more details.
//[c]
//[c] You should have received a copy of the GNU General Public License
//[c] along with this program; if not, write to the Free Software
//[c] Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//[cf]
//[of]:imports
//[c]
import "base/types"
import "base/memory-allocator"
import "text/string"
import "text/string-buffer"
import "linux/unistd"
public [name="c"]
// signal
import func kill (pid_t, int) : int
// signum
equ SIGHUP = 1
equ SIGINT = 2
equ SIGQUIT = 3
equ SIGILL = 4
equ SIGTRAP = 5
equ SIGABRT = 6
equ SIGIOT = 6
equ SIGBUS = 7
equ SIGFPE = 8
equ SIGKILL = 9
equ SIGUSR1 = 10
equ SIGSEGV = 11
equ SIGUSR2 = 12
equ SIGPIPE = 13
equ SIGALRM = 14
equ SIGTERM = 15
equ SIGSTKFLT = 16
equ SIGCLD = SIGCHLD
equ SIGCHLD = 17
equ SIGCONT = 18
equ SIGSTOP = 19
equ SIGTSTP = 20
equ SIGTTIN = 21
equ SIGTTOU = 22
equ SIGURG = 23
equ SIGXCPU = 24
equ SIGXFSZ = 25
equ SIGVTALRM = 26
equ SIGPROF = 27
equ SIGWINCH = 28
equ SIGPOLL = SIGIO
equ SIGIO = 29
equ SIGPWR = 30
equ SIGSYS = 31
equ SIGUNUSED = 31
// wait
import func waitpid (pid_t, [] int, int) : pid_t
equ WNOHANG = 1
equ WEXITSTATUS (status: int) = (status & 0xFF00) >> 8
// fcntl
import func fcntl (int, int) : int
import func fcntl (int, int, int) : int
equ F_GETFL = 3
equ F_SETFL = 4
equ O_NONBLOCK = 0x800
end
//[cf]
//[of]:structures
//[c]
public struct process
public ok : bool
public exit code : int
private pid : pid_t
private stdin : int
private stdout : int
private stderr : int
end
//[cf]
//[c]
//[of]:instance creation
//[of]:create process (command, directory, show window, single output)
//[c]
//[c] Note: show window is unused on unix platform
//[c]
public func create process (
command line: string,
current directory: string,
show window: bool,
single output: bool)
// allocate memory for structure
def m = allocate memory (sizeof local process) : process
// initialize structure
ok (m) = false
exit code (m) = 0
stdin (m) = -1
stdout (m) = -1
stderr (m) = -1
// create the process and start it
start (m,
command line,
current directory,
show window,
single output)
// return description object
return m
end
//[c]
//[c]Sub-Functions:
//[of]: start (m, command, directory, show window, single output)
//[c]
private func start (
m: process,
command line: string,
current directory: string,
show window: bool,
single output: bool)
def stdin: [2] int
def stdout: [2] int
def stderr: [2] int
if pipe (stdin) <> 0; return; end
if pipe (stdout) <> 0; return; end
if single output
// stderr will use same pipe as stout
stderr [0] = dup (stdout [0])
stderr [1] = dup (stdout [1])
else
if pipe (stderr) <> 0; return; end
end
def pid = fork
// fork failed ?
if pid == -1
return
end
// child process ?
if pid == 0
// the stdin-pipe input becomes stdin
close (0)
dup (stdin [0])
close (stdin [0])
close (stdin [1])
// the stdout-pipe output becomes stdout
close (1)
dup (stdout [1])
close (stdout [0])
close(stdout [1])
// the stderr-pipe output becomes stderr
close (2)
dup (stderr [1])
close (stderr [0])
close (stderr [1])
// empty directory means same as parent process
if not empty (current directory)
def res = chdir (current directory)
if res <> 0
_exit (127)
end
end
def args : [4] string
args [0] = "sh"
args [1] = "-c"
args [2] = command line
args [3] = nil
execv ("/bin/sh", args)
_exit (127)
end
close (stdin [0])
close (stdin [1])
close (stderr [1])
close(stdout [1])
fcntl (stdout [0], F_SETFL, O_NONBLOCK)
fcntl (stderr [0], F_SETFL, O_NONBLOCK)
pid (m) = pid
ok (m) = true
stdout (m) = stdout [0]
stderr (m) = stderr [0]
end
//[cf]
//[cf]
//[of]:delete (m)
//[c]
public func delete (m: process)
if is nil (m)
return
end
if stdin (m) <> -1
close (stdin (m))
end
if stdout (m) <> -1
close (stdout (m))
end
if stderr (m) <> -1
close (stderr (m))
end
free memory (m)
end
//[cf]
//[cf]
//[of]:actions
//[of]:stop (m)
//[c]
public func stop (m: process)
kill (pid (m), SIGTERM)
end
//[cf]
//[cf]
//[of]:accessing
//[of]:read stdout (m, stream)
//[c]
public func read stdout (m: process, stream: string buffer)
read pipe (m, stdout (m), stream)
end
//[cf]
//[of]:read stderr (m, stream)
//[c]
public func read stderr (m: process, stream: string buffer)
read pipe (m, stderr (m), stream)
end
//[cf]
//[cf]
//[of]:testing
//[of]:is running (m)
//[c]Checks the status of the process
//[c]
//[c] This method must be invoked periodically to
//[c] detect the termination of the process.
//[c]
//[c] Return Values
//[c] The function returns true if the process is sill running.
//[c]
public func is running (m: process)
def status : [1] int
def is running = waitpid (pid (m), status, WNOHANG) == 0
if ~ is running
exit code (m) = WEXITSTATUS (status [])
end
return is running
end
//[cf]
//[cf]
//[c]
//[of]:private
//[c]
//[of]:read pipe m, handle, string buffer)
//[c]Appends data to the string buffer with chars from a named pipe
//[c]
private func read pipe (m: process, fd: int, stream: string buffer)
equ buffer size = 4096
def buffer : [buffer size] char
repeat
// read bytes
def rd = read (fd, buffer, buffer size)
if rd == 0 || rd == -1
break
end
// append them to the stream
append (stream, buffer, rd)
end
end
//[cf]
//[cf]
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?