-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathProcess.swift
168 lines (145 loc) · 4.18 KB
/
Process.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//
// Process.swift
// Macro
//
// Created by Helge Hess.
// Copyright © 2020-2023 ZeeZide GmbH. All rights reserved.
//
import xsys
import NIO
#if os(Windows)
import WinSDK
#elseif os(Linux)
import Glibc
#else
import Darwin
// importing this from xsys doesn't seem to work
import Foundation // this is for POSIXError : Error
#endif
public enum process {}
public extension process {
static let nextTick = MacroCore.nextTick
}
public extension process { // File System
@inlinable
static func chdir(path: String) throws {
let rc = xsys.chdir(path)
guard rc == 0 else { throw POSIXErrorCode(rawValue: xsys.errno)! }
}
@inlinable
static func cwd() -> String {
let pathMaybe = xsys.getcwd(nil /* malloc */, 0)
assert(pathMaybe != nil, "process has no cwd??")
guard let path = pathMaybe else { return "" }
defer { free(path) }
let s = String(validatingUTF8: path)
assert(s != nil, "could not convert cwd to String?!")
return s ?? "/tmp"
}
}
public extension process { // Process Info
#if os(Windows)
static let platform = "win32"
#elseif os(Linux)
static let platform = "linux"
#else
static let platform = "darwin"
#endif
}
#if !os(Windows)
public extension process { // Process Info
@inlinable
static var pid : Int { return Int(getpid()) }
static let getegid = xsys.getegid
static let geteuid = xsys.geteuid
static let getgid = xsys.getgid
static let getuid = xsys.getuid
// TODO: getgroups, initgroups, setegid, seteuid, setgid, setgroups, setuid
// TODO: hrtime()
// TODO: memoryUsage()
// TODO: title { set get }
// TODO: uptime
// TODO: arch
// TODO: release
}
#endif // !os(Windows)
public extension process { // Run Control
/**
* The exit code to use if `exit` is called without an explicit code,
* defaults to `0` (aka no error).
*
* This can be used to change the default to some error code, so all exits
* will error out, unless a success code is used. For example:
*
* process.exitCode = 1
*
* guard process.argv.count > 1 else { process.exit() } // will fail
* if answer == 42 { process.exit() } // will fail
*
* print("OK, all good.")
* process.exit(0) // explict successful exit
*
*/
static var exitCode : Int {
set { MacroCore.shared.exitCode = newValue }
get { return MacroCore.shared.exitCode }
}
/**
* Terminate the process with the given process exit code.
*
* It no code is passed in, the current value of the `process.exitCode`
* property is used (which itself defaults to 0).
*
* - Parameters:
* - code: The optional exit code, defaults to `process.exitCode`.
*/
@inlinable
static func exit(_ code: Int? = nil) -> Never { MacroCore.shared.exit(code) }
/**
* Terminate the process with the given exit code associated with the
* given value.
*
* This can be used with enums like so:
*
* enum ExitCodes: Int {
* case directoryMissing = 1
* case outOfMemory = 2
* }
*
* - Parameters:
* - code: The optional exit code, defaults to `process.exitCode`.
*/
@inlinable
static func exit<C>(_ code: C) -> Never
where C: RawRepresentable, C.RawValue == Int
{
exit(code.rawValue)
}
@inlinable
@available(*, deprecated, message: "Avoid argument label, just `exit(10)`.")
static func exit(code: Int?) { exit(code) }
}
#if !os(Windows)
public extension process { // Run Control
static let abort = xsys.abort
@inlinable
static func kill(_ pid: Int, _ signal: Int32 = xsys.SIGTERM) throws {
let rc = xsys.kill(pid_t(pid), signal)
guard rc == 0 else { throw POSIXErrorCode(rawValue: xsys.errno)! }
}
@inlinable
static func kill(_ pid: Int, _ signal: String) throws {
var sc : Int32 = xsys.SIGTERM
switch signal.uppercased() {
case "SIGTERM": sc = xsys.SIGTERM
case "SIGHUP": sc = xsys.SIGHUP
case "SIGINT": sc = xsys.SIGINT
case "SIGQUIT": sc = xsys.SIGQUIT
case "SIGKILL": sc = xsys.SIGKILL
case "SIGSTOP": sc = xsys.SIGSTOP
default: emitWarning("unsupported signal: \(signal)")
}
try kill(pid, sc)
}
}
#endif // !os(Windows)