From d45e92bd0b51ca73268f677ecc9b9f65aa26cbe1 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Thu, 31 Mar 2005 01:27:20 +0000
Subject: [PATCH 01/16] Bugfix. (nombre de archivo mal formado)
---
src/sc_suwi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/sc_suwi b/src/sc_suwi
index fe9c5fc..f35090d 100755
--- a/src/sc_suwi
+++ b/src/sc_suwi
@@ -246,7 +246,7 @@ def zip(req, entrega_id):
def zip_path(path, base, zipfd):
paths = os.listdir(path)
for p in paths:
- if os.path.isdir(p):
+ if os.path.isdir(os.path.join(path, p)):
zip_path(os.path.join(path, p), os.path.join(base, p), zipfd)
else:
zipfd.write(os.path.join(path, p), os.path.join(base, p))
--
2.43.0
From a74ade667435b11b48590e8a5f05772207b1f980 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Thu, 31 Mar 2005 23:05:31 +0000
Subject: [PATCH 02/16] Bugfix. Al forkear procesos, la salida estandar y de
error se las ligaba a un pipe. Pero el pipe se leia recien cuando el proceso
forkeado finalizaba. Si se llenaba el buffer del sistema operativo para el
pipe, se quedaba en un 'deadlock', el padre esperando a que termine el hijo y
el hijo esperando que el padre lea del pipe. Ahora se guardan todas las
salidas en disco y se las lee despues.
---
src/sc_test | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/sc_test b/src/sc_test
index 4eab7bb..e936e2e 100755
--- a/src/sc_test
+++ b/src/sc_test
@@ -61,13 +61,14 @@ def compilar(intento, mail):
# Compilo
log.debug('Ejecutando: make -f %s', makefile)
intento.inicioCompila = datetime.datetime.now()
- make = subprocess.Popen(('make', '-f', makefile), stderr=subprocess.PIPE,
+ stderr = file(os.path.join(intento.path, 'make.out'), 'w')
+ make = subprocess.Popen(('make', '-f', makefile), stderr=stderr,
cwd=intento.path)
make.wait()
intento.finCompila = datetime.datetime.now()
log.debug('Fin del comando: make -f %s', makefile)
# Verifico compilación
- stderr = make.stderr.read()
+ stderr = file(os.path.join(intento.path, 'make.out')).read()
intento.compila = not make.returncode
msg = 'Compilación: '
if intento.compila and not stderr:
@@ -144,13 +145,18 @@ def probar(intento, caso_de_prueba, mail):
'cwd': intento.chrootPath(caso_de_prueba),
'close_fds': True,
'preexec_fn': secure_process(intento.chrootPath(caso_de_prueba), uid, gid, tiempo_cpu),
+ 'stdin': None,
+ 'stdout': None,
+ 'stderr': None,
}
if usa_stdin():
options['stdin'] = file(os.path.join(caso_de_prueba.path, 'stdin'), 'r')
if usa_stdout():
- options['stdout'] = subprocess.PIPE
+ stdout_fn = intento.chrootPath(caso_de_prueba) + '.stdout'
+ options['stdout'] = file(stdout_fn, 'w')
if usa_stderr():
- options['stderr'] = subprocess.PIPE
+ stderr_fn = intento.chrootPath(caso_de_prueba) + '.stderr'
+ options['stderr'] = file(stderr_fn, 'w')
# Ejecuto programa
params = ['/tp']
if caso_de_prueba.parametros:
@@ -222,11 +228,11 @@ def probar(intento, caso_de_prueba, mail):
prueba.pasada = True # Asumo que está bien, ya habrá tiempo para cambiarlo
obs = ''
if usa_stdout():
- obs += diff(prueba, mail, proc.stdout.readlines(),
+ obs += diff(prueba, mail, file(stdout_fn).readlines(),
file(os.path.join(caso_de_prueba.path, 'stdout')).readlines(),
caso_de_prueba.nombre + '.stdout', longname='La salida estándar')
if usa_stderr():
- obs += diff(prueba, mail, proc.stderr.readlines(),
+ obs += diff(prueba, mail, file(stderr_fn).readlines(),
file(os.path.join(caso_de_prueba.path, 'stderr')).readlines(),
caso_de_prueba.nombre + '.stderr', longname='La salida de error')
for f in caso_de_prueba.archivosSalida:
--
2.43.0
From 28cf965313c3635a9b4914802262c888607c17e4 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Fri, 1 Apr 2005 05:25:23 +0000
Subject: [PATCH 03/16] Bugfix. Se decodifican los headers MIME con caracteres
no ASCII antes de validar el subject.
---
src/sc_fetch | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/sc_fetch b/src/sc_fetch
index 7a1e407..82bf902 100755
--- a/src/sc_fetch
+++ b/src/sc_fetch
@@ -90,7 +90,7 @@ while (1) {
$mbox_errcount = 0;
logs('Conectado como '.@$mconf['user']." a $mailbox", DEBUG);
if (imap_num_msg($mbox) and $hdr = imap_headerinfo($mbox, 1)) {
- logs("Nuevo mail '{$hdr->subject}' de {$hdr->fromaddress}");
+ logs(sprintf("Nuevo mail '%s' de %s", decode_header($hdr->subject), decode_header($hdr->subject)));
@list($padron, $ej, $ent, $codigo) = validar_cabecera($hdr);
if ($padron) {
logs('Cabecera válida', DEBUG);
@@ -176,7 +176,7 @@ Return-Path: {$mconf['admin']}
X-Mailer: $NAME $VERSION
X-Priority: 5
EOT;
- mail($to, $subject, $body, $headers);
+ mail(decode_header($to), $subject, $body, $headers);
return true;
}
@@ -185,7 +185,8 @@ EOT;
*/
function validar_cabecera($hdr) {
// Subject: padron nro_ej nro_entrega clave_alumno
- if (preg_match('/^\s*(\d{5})\s+([1-4])\.([12])\s+(.*)$/', $hdr->subject, $m)) {
+ $subject = decode_header($hdr->subject);
+ if (preg_match('/^\s*(\d{5})\s+([1-4])\.([12])\s+(.*)$/', $subject, $m)) {
return array_slice($m, 1, 5);
}
return false;
@@ -293,4 +294,13 @@ function fix_eol($str) {
return str_replace("\r\n", "\n", $str);
}
+function decode_header($str) {
+ $elems = imap_mime_header_decode($str);
+ $result = '';
+ foreach ($elems as $elem) {
+ $result .= $elem->text;
+ }
+ return $result;
+}
+
?>
\ No newline at end of file
--
2.43.0
From 022a14d75aad2fa4daac42cbf325fbdf28628c99 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Fri, 1 Apr 2005 15:36:00 +0000
Subject: [PATCH 04/16] =?utf8?q?Se=20mejora=20aclaraci=C3=B3n=20sobre=20su?=
=?utf8?q?bject=20inv=C3=A1lido.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
---
src/sc_fetch | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/sc_fetch b/src/sc_fetch
index 82bf902..9f14318 100755
--- a/src/sc_fetch
+++ b/src/sc_fetch
@@ -124,8 +124,8 @@ while (1) {
. "Recuerde que el formato del asunto es estricto:\n"
. "[padrón] [ejercicio].[entrega] [código]\n\n"
. "Donde [padrón] es su número de padrón, [ejercicio] es el número de\n"
- . "ejercicio (1 a 4), [entrega] el número de entrega (1 o 2) y [código]\n"
- . "es el código verificador que le fue asignado por la cátedra.\n"
+ . "ejercicio (1 a 4), [entrega] el número de entrega (1 entrega, 2 reentrega)\n"
+ . "y [código] es el código verificador que le fue asignado por la cátedra.\n"
);
}
imap_delete($mbox, 1);
--
2.43.0
From 701475008c20603e542c7c59c841298cd84859c3 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Fri, 1 Apr 2005 16:07:22 +0000
Subject: [PATCH 05/16] =?utf8?q?Se=20agrega=20documentaci=C3=B3n=20sobre?=
=?utf8?q?=20l=C3=ADmite=20de=20conexiones=20aceptadas=20por=20inetd.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit
---
doc/README | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/doc/README b/doc/README
index 89a8af8..65b6d46 100644
--- a/doc/README
+++ b/doc/README
@@ -68,4 +68,18 @@ En /var/lib/sercom est
Por omisión el programa guarda el archivo de log en /var/log/sercom.log.
+Una aclaración sobre el servidor de correo a utilizar. El corrector, al
+finalizar una entrega, envía un mail a cada alumno avisando qué intento fue
+tomado como final para corregir. Esto significa que el corrector enviará una
+ráfaga de N mails (siendo N la cantidad de alumnos que entregaron, generalmente
+en el orden de los 100 para la primera entrega). Generalmente los servidores de
+mail tienen una protección y aceptan M conexiones por minuto, siendo M del orden
+de 50 (claro que puede variar, y mucho).
+En el caso particular de inetd, esto se puede configurar, agregando un punto '.'
+y la cantidad máxima de conexiones a aceptar por minuto luego del parámetro
+'wait' (o 'no wait'). Por ejemplo, una configuración apropiada para utilizar el
+corrector bajo inetd+exim sería:
+smtp stream tcp nowait.200 mail /usr/sbin/exim exim -bs
+(donde el 200 significa que se aceptan hasta 200 conexiones por minuto)
+
-- Leandro Lucarella , sáb mar 5 22:16:29 ART 2005
--
2.43.0
From a5e74d07c813bd39e77a5d3253dda1f19768f892 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Sat, 2 Apr 2005 23:31:39 +0000
Subject: [PATCH 06/16] Se ordenan correcciones por padron.
---
src/sc_suwi | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/sc_suwi b/src/sc_suwi
index f35090d..a6b23bc 100755
--- a/src/sc_suwi
+++ b/src/sc_suwi
@@ -21,6 +21,10 @@ import cgitb; cgitb.enable()
#XXX HORRIBLE
PASSWD = conf.get('general', 'cgipw')
+def cmp_correccion_padron(e1, e2):
+ 'Compara 2 entregas, según el padrón del alumno.'
+ return cmp(e1.inscripto.padron, e2.inscripto.padron)
+
def http_header_html(req):
return 'Content-type: text/html\r\n\r\n'
@@ -303,7 +307,9 @@ def correcciones(req, entrega_id):
r = '
Entrega %d.%d del curso %d-%d-%d
\n' \
% (e.nroEjercicio, e.entrega, c.anio, c.cuatrimestre, c.curso)
r += header()
- for c in e.correcciones:
+ correcciones = list(e.correcciones)
+ correcciones.sort(cmp_correccion_padron)
+ for c in correcciones:
r += row(c)
r += footer()
return r
--
2.43.0
From 2c809106fee22f48064720dfdf7dbbc29e4b321d Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Sun, 3 Apr 2005 23:25:27 +0000
Subject: [PATCH 07/16] Se agrega listado de entregas rechazadas.
---
src/sc_suwi | 84 +++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 63 insertions(+), 21 deletions(-)
diff --git a/src/sc_suwi b/src/sc_suwi
index a6b23bc..be47215 100755
--- a/src/sc_suwi
+++ b/src/sc_suwi
@@ -52,6 +52,11 @@ def header(req):
border: medium black solid;
border-collapse: collapse;
}
+ caption
+ {
+ margin: 5pt;
+ font-weight: bold;
+ }
th
{
border: thin black solid;
@@ -270,47 +275,84 @@ def zip(req, entrega_id):
os.unlink(tmpfname)
def correcciones(req, entrega_id):
- def header():
+ def correccion_header():
return '''
-
-
Padrón
-
Pruebas
-
Intentos
-
+
Entregas aceptadas
+
+
+
Padrón
+
Pruebas
+
Intentos
+
+
+
'''
pass
- def footer():
- r = '
\n
\n'
- r += form(req, 'Elegir curso', input_login(req))
- r += form(req, 'Elegir entrega', input_curso(req, e.curso.id))
- r += form(req, 'Bajar entrega en .zip', input_zip(req, entrega_id))
- r += '
\n'
r += form(req, 'Volver', input_entrega(req, i.entrega.id)
+ input_inscripto(req, inscripto_id))
+ #XXX Hack feo y muy hardcodeado para ver los fuentes (morirá con suwi)
+ r += 'ver fuentes
\n'
- def problematico_row(inscripto, entrega):
+ def rechazado_row(inscripto, entrega):
intentos = int(Intento.selectBy(inscriptoID=inscripto.id,
entregaID=entrega.id, connection=conn).count())
return '''
@@ -374,10 +374,10 @@ def correcciones(req, entrega_id):
r += correccion_footer()
inscriptos_ok = set([c.inscripto for c in correcciones])
inscriptos = set([i.inscripto for i in e.intentos])
- r += problematico_header()
+ r += rechazado_header()
for i in inscriptos - inscriptos_ok:
- r += problematico_row(i, e)
- r += problematico_footer()
+ r += rechazado_row(i, e)
+ r += rechazado_footer()
r += footer()
return r
--
2.43.0
From 4d996d9a8b118836ad4de537ead8144b78bf530f Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Thu, 7 Apr 2005 00:27:07 +0000
Subject: [PATCH 14/16] Se usa una forma lambda para comparar por padron.
---
src/sc_suwi | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/sc_suwi b/src/sc_suwi
index bcb0e8c..e4de31d 100755
--- a/src/sc_suwi
+++ b/src/sc_suwi
@@ -21,10 +21,6 @@ import cgitb; cgitb.enable()
#XXX HORRIBLE
PASSWD = conf.get('general', 'cgipw')
-def cmp_correccion_padron(e1, e2):
- 'Compara 2 entregas, según el padrón del alumno.'
- return cmp(e1.inscripto.padron, e2.inscripto.padron)
-
def http_header_html(req):
return 'Content-type: text/html\r\n\r\n'
@@ -367,7 +363,8 @@ def correcciones(req, entrega_id):
r = '
Entrega %d.%d del curso %d-%d-%d
\n' \
% (e.nroEjercicio, e.entrega, c.anio, c.cuatrimestre, c.curso)
correcciones = list(e.correcciones)
- correcciones.sort(cmp_correccion_padron)
+ # Ordena comparando padron
+ correcciones.sort(lambda x, y: cmp(x.inscripto.padron, y.inscripto.padron))
r += correccion_header()
for c in correcciones:
r += correccion_row(c)
--
2.43.0
From 5fbd64ffbcf2259aed83351dcf00ee47a75ff931 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Thu, 7 Apr 2005 00:32:51 +0000
Subject: [PATCH 15/16] Se ordenan las entregas rechazadas.
---
src/sc_suwi | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/sc_suwi b/src/sc_suwi
index e4de31d..fe505a6 100755
--- a/src/sc_suwi
+++ b/src/sc_suwi
@@ -371,8 +371,10 @@ def correcciones(req, entrega_id):
r += correccion_footer()
inscriptos_ok = set([c.inscripto for c in correcciones])
inscriptos = set([i.inscripto for i in e.intentos])
+ rechazados = list(inscriptos - inscriptos_ok)
+ rechazados.sort(lambda x, y: cmp(x.padron, y.padron))
r += rechazado_header()
- for i in inscriptos - inscriptos_ok:
+ for i in rechazados:
r += rechazado_row(i, e)
r += rechazado_footer()
r += footer()
--
2.43.0
From 2865b092c966b47b21285144500ed9465d2f57c1 Mon Sep 17 00:00:00 2001
From: Leandro Lucarella
Date: Sat, 16 Apr 2005 18:36:19 +0000
Subject: [PATCH 16/16] Mejor log.
---
src/sc_test | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/sc_test b/src/sc_test
index 5643e61..f78243a 100755
--- a/src/sc_test
+++ b/src/sc_test
@@ -238,16 +238,16 @@ def probar(intento, caso_de_prueba, mail):
caso_de_prueba.nombre + '.stderr', longname='La salida de error')
for f in caso_de_prueba.archivosSalida:
if f not in prueba.archivosSalida:
- log.debug('Falta el archivo %s y no lo hizo.', f)
+ log.debug('El programa no generó el archivo de salida "%s"', f)
prueba.pasada = False
- obs += "* Falta el archivo de salida '%s'.\n" % f
+ obs += "* El programa no generó el archivo de salida '%s'.\n" % f
continue
obs += diff(prueba, mail,
file(os.path.join(intento.chrootPath(caso_de_prueba), f)).readlines(),
file(os.path.join(caso_de_prueba.pathSalidas, f)).readlines(),
caso_de_prueba.nombre + '.' + f)
for f in prueba.archivosSalida - (caso_de_prueba.archivosSalida | caso_de_prueba.archivosEntrada):
- log.debug('El programa debía generar el archivo %s y no lo hizo.', f)
+ log.debug('Se generó un archivo "%s" que no se esperaba', f)
prueba.pasada = False
obs += "* Se generó un archivo ('%s') que no se esperaba.\n" % f
log.debug('Fin de ejecución de caso de prueba (hijo: %d, ret: %d)',
--
2.43.0