package main import ( "errors" "fmt" "io" "os" "os/exec" "strings" "syscall" ) // Run the given command, showing output. func run_command(command []string) (bool, error) { fmt.Println(strings.Repeat("=", 64)) fmt.Println(command) cmd := exec.Command(command[0], command[1:]...) // Connections stdout, err := cmd.StdoutPipe() if err != nil { return false, fmt.Errorf("Failed getting stdout pipe: %v", err) } var do_autoremove bool = false go func() { var ( buf []byte = make([]byte, 1024) read int err error text string ) for { read, err = stdout.Read(buf) if err != nil { if errors.Is(err, os.ErrClosed) || errors.Is(err, io.EOF) { return } fmt.Println("While reading:", err) return } if read != 0 { text = string(buf[0:read]) fmt.Print(text) if strings.Contains(text, "autoremove") { do_autoremove = true return } } } }() //cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr.Credential = &syscall.Credential{Uid: 0, Gid: 0} err = cmd.Run() fmt.Println(strings.Repeat("=", 50)) return do_autoremove, err } func main() { if os.Geteuid() != 0 { fmt.Println("Use `sudo install -g 0 -o 0 -m 4755 aptgrade ~/bin/aptgrade`") fmt.Println("This program requires SETUID.") os.Exit(2) } _, err := run_command([]string{"/usr/bin/apt", "update"}) if err != nil { fmt.Println("Did you forget to:") fmt.Println(" sudo chown root:root aptgrade") fmt.Println(" sudo chmod a+s aptgrade") fmt.Println("Command failed:", err) os.Exit(2) } do_autoremove, err := run_command([]string{"/usr/bin/apt", "upgrade", "-y"}) if err != nil { fmt.Println("Command failed:", err) os.Exit(2) } if do_autoremove { _, err = run_command([]string{"/usr/bin/apt", "autoremove", "-y"}) if err != nil { fmt.Println("Command failed:", err) os.Exit(2) } } fmt.Println("Done") }