datalackeytools 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +17 -0
- data/bin/datalackey-make +1014 -0
- data/bin/datalackey-run +234 -0
- data/bin/datalackey-shell +1505 -0
- data/bin/datalackey-state +1005 -0
- data/bin/files2object +56 -0
- data/bin/object2files +44 -0
- data/lib/common.rb +9 -0
- data/lib/datalackeylib.rb +638 -0
- metadata +68 -0
data/bin/datalackey-run
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: false
|
3
|
+
|
4
|
+
# Copyright © 2019-2021 Ismo Kärkkäinen
|
5
|
+
# Licensed under Universal Permissive License. See LICENSE.txt.
|
6
|
+
|
7
|
+
# Argument handling and checking
|
8
|
+
# datalackey process
|
9
|
+
# Main loop
|
10
|
+
|
11
|
+
require_relative '../lib/common'
|
12
|
+
require_relative '../lib/datalackeylib'
|
13
|
+
require 'optparse'
|
14
|
+
require 'json'
|
15
|
+
|
16
|
+
|
17
|
+
# Argument handling and checking
|
18
|
+
|
19
|
+
ENV['POSIXLY_CORRECT'] = '1'
|
20
|
+
|
21
|
+
class Arguments
|
22
|
+
attr_reader :directory, :memory, :lackey, :permissions, :terminate_delay, :echo
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@directory = nil
|
26
|
+
@memory = false
|
27
|
+
@lackey = nil
|
28
|
+
@permissions = nil
|
29
|
+
@terminate_delay = nil
|
30
|
+
@echo = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse
|
34
|
+
parser = OptionParser.new do |opts|
|
35
|
+
opts.summary_indent = ''
|
36
|
+
opts.summary_width = 28
|
37
|
+
opts.banner = 'Usage: datalackey-run [options] command params'
|
38
|
+
opts.separator ''
|
39
|
+
opts.separator 'Options:'
|
40
|
+
opts.on_tail('--help', 'Print this help and exit.') do
|
41
|
+
puts opts
|
42
|
+
exit 0
|
43
|
+
end
|
44
|
+
opts.on('--terminate_delay DELAY', 'Seconds to let remaining controller-launched processes to exit, 0 disables.') do |d|
|
45
|
+
@terminate_delay = d
|
46
|
+
end
|
47
|
+
end
|
48
|
+
DatalackeyProcess.options_for_OptionParser(parser, true,
|
49
|
+
proc { |arg| @lackey = arg },
|
50
|
+
proc { |arg| @memory = arg },
|
51
|
+
proc { |arg| @directory = arg },
|
52
|
+
proc { |arg| @permissions = arg },
|
53
|
+
proc { |arg| @echo = arg })
|
54
|
+
parser.parse!
|
55
|
+
# Perform sanity checks on the values.
|
56
|
+
begin
|
57
|
+
@directory, @permissions, @memory =
|
58
|
+
DatalackeyProcess.verify_directory_permissions_memory(
|
59
|
+
@directory, @permissions, @memory)
|
60
|
+
if @terminate_delay.nil?
|
61
|
+
@terminate_delay = 5
|
62
|
+
else
|
63
|
+
@terminate_delay = Float(@terminate_delay)
|
64
|
+
aargh('Terminate delay less than 0.', 1) if @terminate_delay.negative?
|
65
|
+
end
|
66
|
+
@echo = @echo ? proc { |json| put_echo json } : nil
|
67
|
+
rescue ArgumentError => e
|
68
|
+
aargh e.to_s, 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def put_echo(json)
|
74
|
+
begin
|
75
|
+
j = JSON.parse(json)
|
76
|
+
if j.is_a?(Array) && j.size > 3 && j[2] == 'bytes'
|
77
|
+
s = ''
|
78
|
+
(3...j.size).each do |k|
|
79
|
+
s += j[k].chr
|
80
|
+
end
|
81
|
+
j.slice!(3, j.size - 3)
|
82
|
+
j.push s
|
83
|
+
json = JSON.generate(j)
|
84
|
+
end
|
85
|
+
rescue StandardError
|
86
|
+
end
|
87
|
+
puts json
|
88
|
+
end
|
89
|
+
|
90
|
+
arguments = Arguments.new
|
91
|
+
arguments.parse
|
92
|
+
|
93
|
+
# datalackey process
|
94
|
+
begin
|
95
|
+
$lackey_proc = DatalackeyProcess.new(arguments.lackey, arguments.directory, arguments.permissions, arguments.memory)
|
96
|
+
rescue ArgumentError => e
|
97
|
+
puts e.to_s
|
98
|
+
exit 1
|
99
|
+
end
|
100
|
+
$lackey_stderr = StoringReader.new($lackey_proc.stderr)
|
101
|
+
$lackey = DatalackeyIO.new($lackey_proc.stdin, $lackey_proc.stdout, nil, arguments.echo, arguments.echo)
|
102
|
+
|
103
|
+
run_actions = {
|
104
|
+
return: [ { run_running: [ 'run', 'running', '?' ] } ],
|
105
|
+
error: [
|
106
|
+
[ 'run', 'error', '*' ],
|
107
|
+
[ '?', 'error', 'argument', 'invalid' ],
|
108
|
+
[ '?', 'error', 'argument', 'not-integer' ],
|
109
|
+
[ '?', 'missing', '*' ]
|
110
|
+
],
|
111
|
+
note: {
|
112
|
+
run_error_input_failed: [ 'run', 'error', 'input', 'failed' ],
|
113
|
+
run_child_error_output_format: [ [ 'run', 'error', 'format' ],
|
114
|
+
[ 'error', 'format' ] ],
|
115
|
+
run_terminated: [ 'run', 'terminated', '?' ],
|
116
|
+
run_exit: [ 'run', 'exit', '?' ],
|
117
|
+
run_signal: [ 'run', 'signal', '?' ],
|
118
|
+
run_stop: [ 'run', 'stopped', '?' ],
|
119
|
+
run_continue: [ 'run', 'continued' ],
|
120
|
+
run_closed: [ 'run', 'input', 'closed' ]
|
121
|
+
},
|
122
|
+
bytes: [ 'run', 'bytes', '?', '*' ]
|
123
|
+
}
|
124
|
+
|
125
|
+
$output_mutex = Mutex.new
|
126
|
+
$output = []
|
127
|
+
$quitting = false
|
128
|
+
$exit_code = 0
|
129
|
+
|
130
|
+
def run_proc(action, message, vars)
|
131
|
+
$output_mutex.synchronize do
|
132
|
+
case action.first
|
133
|
+
when :error
|
134
|
+
$output.push "ERROR: #{message[3...message.length].join(' ')}"
|
135
|
+
$quitting = true
|
136
|
+
when :note
|
137
|
+
case action[1]
|
138
|
+
when :run_error_input_failed
|
139
|
+
$output.push('Input failed.') unless $quitting
|
140
|
+
when :run_child_error_output_format
|
141
|
+
$output.push 'Output format error.'
|
142
|
+
when :run_terminated
|
143
|
+
$output.push 'Terminated.'
|
144
|
+
$quitting = true
|
145
|
+
when :run_exit
|
146
|
+
$exit_code = vars.last
|
147
|
+
$quitting = true
|
148
|
+
when :run_signal then $output.push "Signal: #{vars.first}"
|
149
|
+
when :run_stop then $output.push "Stopped: #{vars.first}"
|
150
|
+
when :run_continue then $output.push 'Continued.'
|
151
|
+
end
|
152
|
+
when :bytes then $output.push ''.concat(*vars)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
false
|
156
|
+
end
|
157
|
+
|
158
|
+
run_pa = PatternAction.new([ run_actions ],
|
159
|
+
[ proc { |act, msg, vars| run_proc(act, msg, vars) } ])
|
160
|
+
|
161
|
+
# Run the program that was given in the command-line.
|
162
|
+
cmd = [ "datalackey-run-#{Process.pid}", 'run',
|
163
|
+
'in', 'JSON', 'stdin', 'out', 'JSON', 'stdout', 'out', 'bytes', 'stderr',
|
164
|
+
'notify', 'data', 'notify', 'process', 'program'
|
165
|
+
]
|
166
|
+
cmd.concat ARGV
|
167
|
+
$lackey.send(run_pa, cmd, true)
|
168
|
+
|
169
|
+
# Main loop
|
170
|
+
|
171
|
+
def get_output
|
172
|
+
unless $quitting
|
173
|
+
$output_mutex.synchronize do
|
174
|
+
result = $output
|
175
|
+
$output = []
|
176
|
+
return result
|
177
|
+
end
|
178
|
+
else
|
179
|
+
result = $output
|
180
|
+
$output = []
|
181
|
+
return result
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def handle_outputs
|
186
|
+
had_output = false
|
187
|
+
get_output.each do |out|
|
188
|
+
had_output = true
|
189
|
+
puts out
|
190
|
+
end
|
191
|
+
return had_output if $quitting
|
192
|
+
$lackey_stderr.getlines.each do |e|
|
193
|
+
had_output = true
|
194
|
+
aargh e
|
195
|
+
end
|
196
|
+
had_output
|
197
|
+
end
|
198
|
+
|
199
|
+
def id_list_message(command, ids)
|
200
|
+
return if ids.empty?
|
201
|
+
cmd = [ nil, command ] # No need to get replies.
|
202
|
+
cmd.concat ids
|
203
|
+
$lackey.dump(JSON.generate(cmd))
|
204
|
+
end
|
205
|
+
|
206
|
+
terminate_time = nil
|
207
|
+
until $lackey.closed?
|
208
|
+
sleep(0.1) unless handle_outputs
|
209
|
+
next unless $quitting
|
210
|
+
# Here controller has exited.
|
211
|
+
handle_outputs # Left-overs?
|
212
|
+
procs = $lackey.process
|
213
|
+
if procs.empty?
|
214
|
+
$lackey.close # Causes datalackey to exit. Output closing then exits this.
|
215
|
+
next
|
216
|
+
end
|
217
|
+
if terminate_time.nil? # On first quitting, set terminate time and end feeds.
|
218
|
+
terminate_time = Time.new + arguments.terminate_delay
|
219
|
+
id_list_message('end-feed', procs.keys)
|
220
|
+
next # If terminate delay is 0 this gives a little time for normal exit.
|
221
|
+
end
|
222
|
+
next if (Time.new <=> terminate_time) == -1
|
223
|
+
# Time is up and there are running processes.
|
224
|
+
id_list_message('terminate', procs.keys)
|
225
|
+
end
|
226
|
+
|
227
|
+
$lackey_proc.finish
|
228
|
+
$lackey.close
|
229
|
+
$lackey_stderr.close
|
230
|
+
$lackey.finish
|
231
|
+
if $lackey_proc.exit_code != 0 && !$lackey_proc.exit_code.nil?
|
232
|
+
puts("datalackey exit: #{$lackey_proc.exit_code}")
|
233
|
+
end
|
234
|
+
exit $exit_code
|