From: Leandro Lucarella Date: Wed, 23 Feb 2005 03:12:42 +0000 (+0000) Subject: Manejo correcto de parámetros de las pruebas. X-Git-Tag: svn_import~92 X-Git-Url: https://git.llucax.com/software/sercom-old.git/commitdiff_plain/43c9ea2d70a09635f5b4bf9d28070b40ae7b283c?ds=sidebyside Manejo correcto de parámetros de las pruebas. --- diff --git a/src/sc_test b/src/sc_test index 34402ff..6577174 100755 --- a/src/sc_test +++ b/src/sc_test @@ -39,9 +39,8 @@ class secure_process: def sigchld(signum, frame): """Signal handler para SIGCHILD.""" - #global hijo_muerto - #hijo_muerto = True - pass + global hijo_muerto + hijo_muerto = True def sigterm(signum, frame): """Signal handler para SIGTERM y SIGINT.""" @@ -54,7 +53,6 @@ def compilar(intento, intento_dir, entrega_dir, log): makefile = os.path.join(entrega_dir, 'Makefile') if not os.path.exists(makefile): makefile = os.path.join(data_dir, 'Makefile') - shutil.copy(makefile, intento_dir) # Compilo log.debug('Ejecutando: make -f %s', makefile) intento.inicioCompila = datetime.datetime.now() @@ -83,6 +81,7 @@ def preparar(intento_dir, chroot_dir): shutil.move(os.path.join(intento_dir, 'tp'), ejecutable) def probar(intento, caso_de_prueba, uid, gid, chroot_dir, conf, conn, log): + global hijo_muerto # Viene del SIGCHLD # Obtengo datos útiles del caso de prueba tiempo_cpu = caso_de_prueba.tiempoCpu if tiempo_cpu is None: @@ -98,11 +97,13 @@ def probar(intento, caso_de_prueba, uid, gid, chroot_dir, conf, conn, log): stdout = file(os.path.join(intento_dir, 'stdout'), 'w') stderr = file(os.path.join(intento_dir, 'stderr'), 'w') # Ejecuto programa - log.debug('Ejecutando /tp %s', caso_de_prueba.parametros) + params = ['/tp'] + if caso_de_prueba.parametros is not None: + params += params2seq(caso_de_prueba.parametros) + log.debug('Ejecutando %s', ' '.join(params)) os.seteuid(0) # Dios! (para chroot) - # FIXME caso_de_prueba.parametros try: - proc = subprocess.Popen('/tp', stdout=stdout, stderr=stderr, #stdin=stdin, + proc = subprocess.Popen(params, stdout=stdout, stderr=stderr, #stdin=stdin, preexec_fn=secure_process(chroot_dir, uid, gid, tiempo_cpu)) except Exception, e: # FIXME poner en el manejo de exceptiones estandar try: @@ -111,7 +112,8 @@ def probar(intento, caso_de_prueba, uid, gid, chroot_dir, conf, conn, log): except: raise os.seteuid(uid) # Mortal de nuevo - time.sleep(tiempo_cpu) + if not hijo_muerto: # Recibido por el sigchld, para saber si murió + time.sleep(tiempo_cpu) # Si el proceso sigue andando lo tenemos que matar if proc.poll() is None: log.debug('La prueba tardó más del tiempo permitido (%d segundos)', @@ -161,17 +163,83 @@ def probar(intento, caso_de_prueba, uid, gid, chroot_dir, conf, conn, log): log.debug('Prueba OK: %s', prueba) return prueba +def params2seq(params): + r"""Parsea un string de forma similar al bash, separando por espacios y + teniendo en cuenta comillas simples y dobles para agrupar. Para poner + comillas se puede usar el \ como caracter de escape (\' y \") y también + interpreta \n y \t. Devuelve una lista con los parámetros encontrados.""" + # Constantes + SEP, TOKEN, DQUOTE, SQUOTE = ' ', None, '"', "'" + seq = [] + buff = '' + escape = False + state = SEP + for c in params: + # Es un caracter escapado + if escape: + if c == 'n': + buff += '\n' + elif c == 't': + buff += '\t' + else: + buff += c + escape = False + continue + # Es una secuencia de escape + if c == r'\\': + escape = True + continue + # Si está buscando espacios + if state == SEP: + if c == SEP: + continue + else: + state = TOKEN # Encontró + if state == TOKEN: + if c == DQUOTE: + state = DQUOTE + continue + if c == SQUOTE: + state = SQUOTE + continue + if c == SEP: + state = SEP + seq.append(buff) + buff = '' + continue + buff += c + continue + if state == DQUOTE: + if c == DQUOTE: + state = TOKEN + continue + buff += c + continue + if state == SQUOTE: + if c == SQUOTE: + state = TOKEN + continue + buff += c + continue + raise Exception, 'No tiene sentido' + if state == DQUOTE or state == SQUOTE: + raise Exception, 'Parse error, falta cerrar comilla (%s)' % state + if buff: + seq.append(buff) + return seq + # Conecto señales -signal.signal(signal.SIGCHLD, sigchld) signal.signal(signal.SIGTERM, sigterm) signal.signal(signal.SIGINT, sigterm) +signal.signal(signal.SIGCHLD, sigchld) +hijo_muerto = False # Inicializo conf, conn, log = sercom.init('test') log.info('Iniciado') # Obtengo id de usuario con el cual ejecutar las pruebas -(uid, gid) = pwd.getpwnam(conf.get('general', 'user'))[2:4] +uid, gid = pwd.getpwnam(conf.get('general', 'user'))[2:4] # Cambio UID efectivo os.seteuid(uid)