Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sudoをつけなくてもPBMを起動できるようにする #281

Merged
merged 8 commits into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## unrelease
* sudoをつけずにPBMを起動できるようになりました

## [0.3.11] 2023-12-13
* 起動時の安定性向上
* systemd unit pbm.serviceをRestart=noにしました
Expand Down
9 changes: 9 additions & 0 deletions lib/procon_bypass_man.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
require_relative "procon_bypass_man/support/simple_tcp_server"
require_relative "procon_bypass_man/support/proccess_cheacker"
require_relative "procon_bypass_man/support/output_report_generator"
require_relative "procon_bypass_man/support/sudo_need_password_checker"
require_relative "procon_bypass_man/support/shell_runner"
require_relative "procon_bypass_man/procon_display"
require_relative "procon_bypass_man/background"
require_relative "procon_bypass_man/commands"
Expand Down Expand Up @@ -105,6 +107,13 @@ def self.run(setting_path: nil)
# デバイスの接続フェーズ
begin
gadget, procon = ProconBypassMan::DeviceConnection::Command.execute!
rescue ProconBypassMan::DeviceConnection::SetupIncompleteError
ProconBypassMan::SendErrorCommand.execute(error: "The program is terminating because it encountered a request for the sudo password. Please review your sudo settings.", stdout: true)
ProconBypassMan::DeviceStatus.change_to_procon_not_found_error! # NOTE: procon_not_found_errorではないけど、めんどいのでこのステータスにする
ProconBypassMan::NeverExitAccidentally.exit_if_allow_at_config do
terminate_pbm
end
return
rescue ProconBypassMan::DeviceConnection::NotFoundProconError
ProconBypassMan::SendErrorCommand.execute(error: "プロコンが見つかりませんでした。")
ProconBypassMan::DeviceStatus.change_to_procon_not_found_error!
Expand Down
1 change: 1 addition & 0 deletions lib/procon_bypass_man/device_connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class BytesMismatchError < StandardError; end
class NotFoundProconError < StandardError; end
class TimeoutErrorInConditionalRoute < StandardError; end
class TimeoutError < StandardError; end
class SetupIncompleteError < StandardError; end
end

require_relative "device_connection/executor"
Expand Down
2 changes: 1 addition & 1 deletion lib/procon_bypass_man/device_connection/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def self.execute!(retry_count: 0)

retry_count = retry_count + 1
retry
rescue ProconBypassMan::DeviceConnection::NotFoundProconError => e
rescue ProconBypassMan::DeviceConnection::NotFoundProconError, ProconBypassMan::DeviceConnection::SetupIncompleteError => e
raise
end

Expand Down
10 changes: 9 additions & 1 deletion lib/procon_bypass_man/device_connection/executor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,22 +150,30 @@ def procon
@procon
end

GADGET_PATH = '/dev/hidg0'
def init_devices
unless SudoNeedPasswordChecker.execute!
raise ProconBypassMan::DeviceConnection::SetupIncompleteError
end

if @initialized_devices
return
end
ProconBypassMan::UsbDeviceController.init
ProconBypassMan::UsbDeviceController.reset

if path = ProconBypassMan::DeviceProconFinder.find
ShellRunner.execute("sudo chmod 777 #{path}")
@procon = File.open(path, "w+b")
ProconBypassMan.logger.info "proconのデバイスファイルは#{path}を使います"
else
raise(ProconBypassMan::DeviceConnection::NotFoundProconError)
end

begin
@gadget = File.open('/dev/hidg0', "w+b")
ShellRunner.execute('sudo chmod 777 -R /sys/kernel/config/usb_gadget/procon')
ShellRunner.execute("sudo chmod 777 #{GADGET_PATH}")
@gadget = File.open(GADGET_PATH, "w+b")
rescue Errno::ENXIO => e
# /dev/hidg0 をopenできないときがある
ProconBypassMan::SendErrorCommand.execute(error: "Errno::ENXIOが起きたのでresetします.\n #{e.full_message}", stdout: false)
Expand Down
2 changes: 1 addition & 1 deletion lib/procon_bypass_man/support/renice_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def self.change_priority(to: , pid: )
raise "unknown priority"
end
ProconBypassMan.logger.debug { "[SHELL] #{cmd}" }
`#{cmd}`
`sudo #{cmd}`
end
end
end
11 changes: 11 additions & 0 deletions lib/procon_bypass_man/support/shell_runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class ShellRunner
# @param [String] command
# @param [Boolean] stdout
# @return [void]
def self.execute(command, stdout: true)
system(command) # TODO: ここでエラーが起きたときに、エラーをログに出力する
if stdout
ProconBypassMan.logger.info("[SHELL]: #{command}")
end
end
end
6 changes: 6 additions & 0 deletions lib/procon_bypass_man/support/sudo_need_password_checker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class SudoNeedPasswordChecker
# @return [boolean] falseならパスワードが必要
def self.execute!
system('sudo -n true 2>/dev/null')
end
end
1 change: 0 additions & 1 deletion lib/procon_bypass_man/support/usb_device_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def init
EOH

`bash -c '#{shell}'`
sleep(1)
end

def initialized?
Expand Down
10 changes: 7 additions & 3 deletions spec/lib/procon_bypass_man/support/simple_tcp_server_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
require 'socket'
require 'procon_bypass_man/support/simple_tcp_server'
require 'spec_helper'

describe SimpleTCPServer do
let(:host) { '0.0.0.0' }
let(:port) { 8000 }
let(:port) {
server = TCPServer.new(host, 0)
port = server.addr[1]
server.close
port
}
let(:server) { SimpleTCPServer.new(host, port) }
let(:server_thread) { Thread.new { server.run } }

Expand Down
11 changes: 11 additions & 0 deletions spec/lib/procon_bypass_man_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@
end
end

context 'SetupIncompleteErrorが起きるとき' do
before do
allow(ProconBypassMan::DeviceConnection::Command).to receive(:execute!) { raise ProconBypassMan::DeviceConnection::SetupIncompleteError }
end

it do
expect{ subject }.to raise_error(SystemExit)
expect(ProconBypassMan::DeviceStatus.current).to eq(ProconBypassMan::DeviceStatus::PROCON_NOT_FOUND_ERROR)
end
end

context 'NotFoundProconErrorが起きるとき' do
before do
allow(ProconBypassMan::DeviceConnection::Command).to receive(:execute!) { raise ProconBypassMan::DeviceConnection::NotFoundProconError }
Expand Down
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
allow(ProconBypassMan::Background::JobQueue).to receive(:enable?) { false }
allow(ProconBypassMan::RemoteAction::QueueOverProcess).to receive(:enable?) { false }
allow(ProconBypassMan::Procon::PerformanceMeasurement::QueueOverProcess).to receive(:enable?) { false }
allow(SudoNeedPasswordChecker).to receive(:execute!) { true }
allow(ProconBypassMan::ReniceCommand).to receive(:change_priority)

allow(ProconBypassMan::HttpClient::HttpRequest::Get).to receive(:new)
allow(ProconBypassMan::HttpClient::HttpRequest::Post).to receive(:new)
Expand Down
Loading