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 + -
显示快捷键?