File size: 2,786 Bytes
1e75d97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import gradio as gr
import subprocess, tempfile, os, uuid, resource

# --- Función principal --------------------------------------------------------
def compile_and_run(code: str, stdin: str = "") -> str:
    """
    Compila el código C, lo ejecuta y devuelve la salida (stdout + stderr).
    Se aplican límites de tiempo y memoria para evitar abusos.
    """
    # 1. Crear carpeta temporal única
    tmpdir = tempfile.mkdtemp(prefix="c_exec_")
    c_path  = os.path.join(tmpdir, "main.c")
    bin_path = os.path.join(tmpdir, "main")

    # 2. Guardar código
    with open(c_path, "w") as f:
        f.write(code)

    # 3. Compilar
    compile_proc = subprocess.run(
        ["gcc", c_path, "-O2", "-std=c11", "-pipe", "-o", bin_path],
        capture_output=True, text=True, timeout=10
    )
    if compile_proc.returncode != 0:
        return f"❌ Error de compilación:\n{compile_proc.stderr}"

    # 4. Establecer límites de recursos antes de ejecutar
    def limit_resources():
        resource.setrlimit(resource.RLIMIT_CPU, (2, 2))           # 2 s CPU
        resource.setrlimit(resource.RLIMIT_AS, (128*1024*1024,   # 128 MB
                                               128*1024*1024))

    # 5. Ejecutar binario generado
    try:
        run_proc = subprocess.run(
            [bin_path],
            input=stdin,
            text=True,
            capture_output=True,
            timeout=2,            # tiempo real (wall-clock)
            preexec_fn=limit_resources
        )
    except subprocess.TimeoutExpired:
        return "⏰ Tiempo de ejecución excedido (2 s)."

    out  = run_proc.stdout
    err  = run_proc.stderr
    exit = run_proc.returncode

    response = f"⏹ Código de salida: {exit}\n"
    if out:
        response += f"\n📤 STDOUT\n{out}"
    if err:
        response += f"\n⚠️ STDERR\n{err}"
    return response.strip()


# --- UI en Gradio -------------------------------------------------------------
title       = "Compilador C online (42 Edition)"
description = """
Ejecuta fragmentos de **lenguaje C** con límite de recursos.
También disponible como endpoint REST (`/run/predict`).
"""

demo = gr.Interface(
        fn          = compile_and_run,
        inputs      = [
            gr.Code(language="c", label="Código C"),
            gr.Textbox(lines=3, placeholder="Entrada estándar (stdin)", label="Stdin (opcional)")
        ],
        outputs     = gr.Textbox(label="Resultado"),
        title       = title,
        description = description,
        examples    = [
            [r"#include <stdio.h>\nint main(){printf(\"Hola 42!\\n\");}", ""],
            [r"#include <stdio.h>\nint main(){int a,b;scanf(\"%d %d\",&a,&b);printf(\"%d\\n\",a+b);}", "3 4"]
        ],
)

if __name__ == "__main__":
    demo.launch()