diff --git a/src/server.rs b/src/server.rs index a113be3..a6bb947 100644 --- a/src/server.rs +++ b/src/server.rs @@ -5,7 +5,9 @@ use std::{ io::prelude::*, io::{BufReader, Read, Write}, net::{TcpListener, TcpStream}, + os::unix::fs::PermissionsExt, path::Path, + process::Command, }; use threadpool::ThreadPool; @@ -183,10 +185,15 @@ where &'a W: Write, { let path = req.file_path(); - let file = File::open(&path)?; - let reader = BufReader::new(file); + + let reader = if is_executable(&path) { + sh(&path, &[&req.selector, &req.host, &req.port.to_string()])? + } else { + fs::read_to_string(path)? + }; + for line in reader.lines() { - let mut line = line?.trim_end_matches("\r\n").to_string(); + let mut line = line.trim_end_matches("\r").to_string(); match line.chars().filter(|&c| c == '\t').count() { 0 => { if line.chars().nth(0) != Some('i') { @@ -229,3 +236,22 @@ fn file_type(dir: &fs::DirEntry) -> ItemType { ItemType::Error } } + +/// Is the file at the given path executable? +fn is_executable(path: &str) -> bool { + if let Ok(meta) = fs::metadata(path) { + meta.permissions().mode() & 0o111 != 0 + } else { + false + } +} + +/// Run a script and return its output. +fn sh(path: &str, args: &[&str]) -> Result { + let output = Command::new(path).args(args).output()?; + if output.status.success() { + Ok(std::str::from_utf8(&output.stdout)?.to_string()) + } else { + Ok(std::str::from_utf8(&output.stderr)?.to_string()) + } +}