Fix: don't need sudo if we're root + other aesthetics
This commit is contained in:
parent
4d0086df41
commit
ab104bb7bc
7 changed files with 125 additions and 80 deletions
|
@ -6,11 +6,12 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||||
|
"github.com/klauspost/cpuid/v2"
|
||||||
|
|
||||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/uname"
|
"github.com/HikariKnight/quickpassthrough/pkg/uname"
|
||||||
"github.com/klauspost/cpuid/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
|
@ -30,6 +31,7 @@ type Config struct {
|
||||||
Path *Path
|
Path *Path
|
||||||
Gpu_Group string
|
Gpu_Group string
|
||||||
Gpu_IDs []string
|
Gpu_IDs []string
|
||||||
|
IsRoot bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the path to all the config files
|
// Gets the path to all the config files
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||||
|
"github.com/gookit/color"
|
||||||
|
|
||||||
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
||||||
lsiommu "github.com/HikariKnight/quickpassthrough/internal/lsiommu"
|
"github.com/HikariKnight/quickpassthrough/internal/lsiommu"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
||||||
"github.com/gookit/color"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SelectGPU(config *configs.Config) {
|
func SelectGPU(config *configs.Config) {
|
||||||
|
|
|
@ -4,11 +4,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/gookit/color"
|
||||||
|
|
||||||
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
||||||
lsiommu "github.com/HikariKnight/quickpassthrough/internal/lsiommu"
|
"github.com/HikariKnight/quickpassthrough/internal/lsiommu"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
||||||
"github.com/gookit/color"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func selectUSB(config *configs.Config) {
|
func selectUSB(config *configs.Config) {
|
||||||
|
|
|
@ -5,18 +5,20 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/gookit/color"
|
||||||
|
"golang.org/x/term"
|
||||||
|
|
||||||
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
"github.com/HikariKnight/quickpassthrough/internal/configs"
|
||||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
"github.com/HikariKnight/quickpassthrough/pkg/menu"
|
||||||
"github.com/HikariKnight/quickpassthrough/pkg/uname"
|
"github.com/HikariKnight/quickpassthrough/pkg/uname"
|
||||||
"github.com/gookit/color"
|
|
||||||
"golang.org/x/term"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func prepModules(config *configs.Config) {
|
func prepModules(config *configs.Config) {
|
||||||
|
@ -48,6 +50,43 @@ func prepModules(config *configs.Config) {
|
||||||
finalize(config)
|
finalize(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func finalizeNotice(isRoot bool) {
|
||||||
|
color.Print(`
|
||||||
|
The configuration files have been generated and are located inside the "config" folder
|
||||||
|
|
||||||
|
* The "kernel_args" file contains kernel arguments that your bootloader needs
|
||||||
|
* The "qemu" folder contains files that may be needed for passthrough
|
||||||
|
* The files inside the "etc" folder must be copied to your system.
|
||||||
|
|
||||||
|
<red>Verify that these files are correctly formated/edited!</>
|
||||||
|
|
||||||
|
Once all files have been copied, the following steps must be taken:
|
||||||
|
|
||||||
|
* bootloader configuration must be updated
|
||||||
|
* initramfs must be rebuilt
|
||||||
|
|
||||||
|
`)
|
||||||
|
switch isRoot {
|
||||||
|
case true:
|
||||||
|
color.Print("This program can do this for you, if desired.\n")
|
||||||
|
default:
|
||||||
|
color.Print(`This program can do this for you, however your sudo password is required.
|
||||||
|
To avoid this:
|
||||||
|
|
||||||
|
* press CTRL+C and perform the steps mentioned above manually.
|
||||||
|
OR
|
||||||
|
* run ` + os.Args[0] + ` as root.
|
||||||
|
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
color.Print(`
|
||||||
|
If you want to go back and change something, choose Back.
|
||||||
|
|
||||||
|
NOTE: A backup of the original files from the first run can be found in the backup folder
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func finalize(config *configs.Config) {
|
func finalize(config *configs.Config) {
|
||||||
// Clear the screen
|
// Clear the screen
|
||||||
command.Clear()
|
command.Clear()
|
||||||
|
@ -56,60 +95,45 @@ func finalize(config *configs.Config) {
|
||||||
title := color.New(color.BgHiBlue, color.White, color.Bold)
|
title := color.New(color.BgHiBlue, color.White, color.Bold)
|
||||||
title.Println("Finalizing configuration")
|
title.Println("Finalizing configuration")
|
||||||
|
|
||||||
color.Print(
|
isRoot := os.Getuid() == 0
|
||||||
"The configuration files have been generated and are\n",
|
|
||||||
"located inside the \"config\" folder\n",
|
|
||||||
"\n",
|
|
||||||
"* The \"kernel_args\" file contains kernel arguments that your bootloader needs\n",
|
|
||||||
"* The \"qemu\" folder contains files that might be\n neccessary for passing through the GPU\n",
|
|
||||||
"* The files inside the \"etc\" folder must be copied to your system.\n",
|
|
||||||
" NOTE: Verify that these files are correctly formated/edited!\n",
|
|
||||||
"* Once all files have been copied, you need to update your bootloader and rebuild\n",
|
|
||||||
" your initramfs using the tools to do so by your system.\n",
|
|
||||||
"\n",
|
|
||||||
"This program can do this for you, however the program will have to\n",
|
|
||||||
"type your password to sudo using STDIN, to avoid using STDIN press CTRL+C\n",
|
|
||||||
"and copy the files, update your bootloader and rebuild your initramfs manually.\n",
|
|
||||||
"If you want to go back and change something, choose Back\n",
|
|
||||||
"\nNOTE: A backup of the original files from the first run can be found in the backup folder\n",
|
|
||||||
)
|
|
||||||
|
|
||||||
// Make a choice of going next or back
|
config.IsRoot = isRoot
|
||||||
choice := menu.Next("Press Next to continue with sudo using STDIN, ESC to exit or Back to go back.")
|
|
||||||
|
|
||||||
// Parse the choice
|
finalizeNotice(isRoot)
|
||||||
switch choice {
|
|
||||||
|
// Make a choice of going next or back and parse the choice
|
||||||
|
switch menu.Next("Press Next to continue with sudo using STDIN, ESC to exit or Back to go back.") {
|
||||||
case "next":
|
case "next":
|
||||||
installPassthrough(config)
|
installPassthrough(config)
|
||||||
|
|
||||||
case "back":
|
case "back":
|
||||||
// Go back
|
// Go back
|
||||||
disableVideo(config)
|
disableVideo(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func installPassthrough(config *configs.Config) {
|
func installPassthrough(config *configs.Config) {
|
||||||
// Get the user data
|
// Get the user data
|
||||||
user, err := user.Current()
|
currentUser, err := user.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide a password prompt
|
if !config.IsRoot {
|
||||||
fmt.Printf("[sudo] password for %s: ", user.Username)
|
// Provide a password prompt
|
||||||
bytep, err := term.ReadPassword(int(syscall.Stdin))
|
fmt.Printf("[sudo] password for %s: ", currentUser.Username)
|
||||||
if err != nil {
|
bytep, err := term.ReadPassword(syscall.Stdin)
|
||||||
os.Exit(1)
|
if err != nil {
|
||||||
}
|
os.Exit(1)
|
||||||
fmt.Print("\n")
|
}
|
||||||
|
fmt.Print("\n")
|
||||||
|
|
||||||
// Elevate with sudo
|
// Elevate with sudo
|
||||||
command.Elevate(
|
command.Elevate(
|
||||||
base64.StdEncoding.EncodeToString(
|
base64.StdEncoding.EncodeToString(
|
||||||
bytep,
|
bytep,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Make an output string
|
// Make an output string
|
||||||
var output string
|
var output string
|
||||||
|
@ -151,10 +175,29 @@ func installPassthrough(config *configs.Config) {
|
||||||
fmt.Printf("%s\n", output)
|
fmt.Printf("%s\n", output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
execAndLogSudo := func(cmd string) {
|
||||||
|
if !config.IsRoot && !strings.HasPrefix(cmd, "sudo") {
|
||||||
|
cmd = fmt.Sprintf("sudo %s", cmd)
|
||||||
|
}
|
||||||
|
// Write to logger
|
||||||
|
logger.Printf("Executing: %s\n", cmd)
|
||||||
|
|
||||||
|
// Update initramfs
|
||||||
|
fmt.Printf("Executing: %s\nSee debug.log for detailed output\n", cmd)
|
||||||
|
cs := strings.Fields(cmd)
|
||||||
|
r := exec.Command(cs[0], cs[1:]...)
|
||||||
|
|
||||||
|
cmd_out, _ := r.CombinedOutput()
|
||||||
|
|
||||||
|
// Write to logger
|
||||||
|
logger.Printf(string(cmd_out) + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the config files for the system we have
|
// Copy the config files for the system we have
|
||||||
initramfsFile := fmt.Sprintf("%s/modules", config.Path.INITRAMFS)
|
initramfsFile := fmt.Sprintf("%s/modules", config.Path.INITRAMFS)
|
||||||
dracutFile := fmt.Sprintf("%s/vfio.conf", config.Path.DRACUT)
|
dracutFile := fmt.Sprintf("%s/vfio.conf", config.Path.DRACUT)
|
||||||
if fileio.FileExist(initramfsFile) {
|
switch {
|
||||||
|
case fileio.FileExist(initramfsFile):
|
||||||
// Copy initramfs-tools module to system
|
// Copy initramfs-tools module to system
|
||||||
output = configs.CopyToSystem(initramfsFile, "/etc/initramfs-tools/modules")
|
output = configs.CopyToSystem(initramfsFile, "/etc/initramfs-tools/modules")
|
||||||
fmt.Printf("%s\n", output)
|
fmt.Printf("%s\n", output)
|
||||||
|
@ -163,18 +206,9 @@ func installPassthrough(config *configs.Config) {
|
||||||
output = configs.CopyToSystem(config.Path.ETCMODULES, "/etc/modules")
|
output = configs.CopyToSystem(config.Path.ETCMODULES, "/etc/modules")
|
||||||
fmt.Printf("%s\n", output)
|
fmt.Printf("%s\n", output)
|
||||||
|
|
||||||
// Write to logger
|
execAndLogSudo("update-initramfs -u")
|
||||||
logger.Printf("Executing: sudo update-initramfs -u\n")
|
|
||||||
|
|
||||||
// Update initramfs
|
case fileio.FileExist(dracutFile):
|
||||||
fmt.Println("Executed: sudo update-initramfs -u\nSee debug.log for detailed output")
|
|
||||||
cmd_out, cmd_err, _ := command.RunErr("sudo", "update-initramfs", "-u")
|
|
||||||
|
|
||||||
cmd_out = append(cmd_out, cmd_err...)
|
|
||||||
|
|
||||||
// Write to logger
|
|
||||||
logger.Printf(strings.Join(cmd_out, "\n"))
|
|
||||||
} else if fileio.FileExist(dracutFile) {
|
|
||||||
// Copy dracut config to /etc/dracut.conf.d/vfio
|
// Copy dracut config to /etc/dracut.conf.d/vfio
|
||||||
output = configs.CopyToSystem(dracutFile, "/etc/dracut.conf.d/vfio")
|
output = configs.CopyToSystem(dracutFile, "/etc/dracut.conf.d/vfio")
|
||||||
fmt.Printf("%s\n", output)
|
fmt.Printf("%s\n", output)
|
||||||
|
@ -182,31 +216,15 @@ func installPassthrough(config *configs.Config) {
|
||||||
// Get systeminfo
|
// Get systeminfo
|
||||||
sysinfo := uname.New()
|
sysinfo := uname.New()
|
||||||
|
|
||||||
// Write to logger
|
execAndLogSudo(fmt.Sprintf("dracut -f -v --kver %s\n", sysinfo.Release))
|
||||||
logger.Printf("Executing: sudo dracut -f -v --kver %s\n", sysinfo.Release)
|
|
||||||
|
|
||||||
// Update initramfs
|
case fileio.FileExist(config.Path.MKINITCPIO):
|
||||||
fmt.Printf("Executed: sudo dracut -f -v --kver %s\nSee debug.log for detailed output", sysinfo.Release)
|
|
||||||
_, cmd_err, _ := command.RunErr("sudo", "dracut", "-f", "-v", "--kver", sysinfo.Release)
|
|
||||||
|
|
||||||
// Write to logger
|
|
||||||
logger.Printf(strings.Join(cmd_err, "\n"))
|
|
||||||
} else if fileio.FileExist(config.Path.MKINITCPIO) {
|
|
||||||
// Copy dracut config to /etc/dracut.conf.d/vfio
|
// Copy dracut config to /etc/dracut.conf.d/vfio
|
||||||
output = configs.CopyToSystem(config.Path.MKINITCPIO, "/etc/mkinitcpio.conf")
|
output = configs.CopyToSystem(config.Path.MKINITCPIO, "/etc/mkinitcpio.conf")
|
||||||
fmt.Printf("%s\n", output)
|
fmt.Printf("%s\n", output)
|
||||||
|
|
||||||
// Write to logger
|
execAndLogSudo("mkinitcpio -P")
|
||||||
logger.Printf("Executing: sudo mkinitcpio -P")
|
|
||||||
|
|
||||||
// Update initramfs
|
|
||||||
fmt.Println("Executed: sudo mkinitcpio -P\nSee debug.log for detailed output")
|
|
||||||
cmd_out, cmd_err, _ := command.RunErr("sudo", "mkinitcpio", "-P")
|
|
||||||
|
|
||||||
cmd_out = append(cmd_out, cmd_err...)
|
|
||||||
|
|
||||||
// Write to logger
|
|
||||||
logger.Printf(strings.Join(cmd_out, "\n"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure prompt end up on next line
|
// Make sure prompt end up on next line
|
||||||
|
|
23
internal/pages/06_finalize_test.go
Normal file
23
internal/pages/06_finalize_test.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFinalizeNotice(t *testing.T) {
|
||||||
|
msg := "\n%s\nprinting the finalize notice for manual review, this test should always pass.\n%s\n\n"
|
||||||
|
divider := strings.Repeat("-", len(msg)-12)
|
||||||
|
t.Logf(msg, divider, divider)
|
||||||
|
t.Log("\n\nWith isRoot == true:\n\n")
|
||||||
|
|
||||||
|
finalizeNotice(true)
|
||||||
|
|
||||||
|
println("\n\n")
|
||||||
|
|
||||||
|
t.Log("\n\nWith isRoot == false:\n\n")
|
||||||
|
|
||||||
|
finalizeNotice(false)
|
||||||
|
|
||||||
|
println("\n\n")
|
||||||
|
}
|
|
@ -14,8 +14,8 @@ import (
|
||||||
// This is where we build everything
|
// This is where we build everything
|
||||||
func Tui() {
|
func Tui() {
|
||||||
// Log all errors to a new logfile (super useful feature of BubbleTea!)
|
// Log all errors to a new logfile (super useful feature of BubbleTea!)
|
||||||
os.Remove("debug.log")
|
_ = os.Rename("quickpassthrough_debug.log", "quickpassthrough_debug_old.log")
|
||||||
logfile, err := tea.LogToFile("debug.log", "")
|
logfile, err := tea.LogToFile("quickpassthrough_debug.log", "")
|
||||||
errorcheck.ErrorCheck(err, "Error creating log file")
|
errorcheck.ErrorCheck(err, "Error creating log file")
|
||||||
defer logfile.Close()
|
defer logfile.Close()
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ func Run(binary string, args ...string) ([]string, error) {
|
||||||
return outputs, err
|
return outputs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is just like command.Run() but also returns STDERR
|
// RunErr is just like command.Run() but also returns STDERR
|
||||||
func RunErr(binary string, args ...string) ([]string, []string, error) {
|
func RunErr(binary string, args ...string) ([]string, []string, error) {
|
||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ func RunErr(binary string, args ...string) ([]string, []string, error) {
|
||||||
return outputs, outerrs, err
|
return outputs, outerrs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// This functions runs the command "sudo -Sk -- echo", this forces sudo
|
// Elevate elevates this functions runs the command "sudo -Sk -- echo",
|
||||||
// to re-authenticate and lets us enter the password to STDIN
|
// this forces sudo to re-authenticate and lets us enter the password to STDIN
|
||||||
// giving us the ability to run sudo commands
|
// giving us the ability to run sudo commands
|
||||||
func Elevate(password string) {
|
func Elevate(password string) {
|
||||||
// Do a simple sudo command to just authenticate with sudo
|
// Do a simple sudo command to just authenticate with sudo
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue