     cmd.append(url)
     cmd.append(contentsOf: ["-o", output])
     try run(cmd)
+}
+
+func wget(url: String, output: String, verbose: Bool = false) throws {
+    guard hasCommand("wget") else {
+        throw Error.commandNotFound
+    }
+
+    var cmd = ["wget"]
+    if !verbose {
+        cmd.append("-q")
+    }
+    cmd.append(url)
+    cmd.append(contentsOf: ["-O", output])
+    try run(cmd)
+}
+
+func download(url: String, output: String, verbose: Bool = false, followRedirect: Bool = true) throws {
+    do {
+        try curl(url: url, output: output, verbose: verbose, followRedirect: followRedirect)
+    } catch Error.commandNotFound {
+        // curl may not be available
+        try wget(url: url, output: output, verbose: verbose)
+    }
 }
 
 func unpack(archive: String, verbose: Bool = false) throws {

enum Error: ErrorProtocol { // Errors pertaining to running commands
    case system(Int32)
    case cancelled
    case terminalSize
}

func run(_ command: String) throws {
    print("### CMD: \(command)")
    let result = system(command)

    if result == 2 {

    }
}

func hasCommand(_ name: String) -> Bool {
    return system("which \(name) > /dev/null 2>&1") == 0
}

func curl(url: String, output: String, verbose: Bool = false, followRedirect: Bool = true) throws {
    guard hasCommand("curl") else {
        throw Error.commandNotFound
    }

    var cmd = ["curl"]
    if !verbose {
        cmd.append("-s")
