]> git.llucax.com Git - z.facultad/75.08/llamadas.git/blobdiff - doc/Informe7508.lyx
Agrego afimonio_daemon.sh y creo que con eso está finiquitado el informe.
[z.facultad/75.08/llamadas.git] / doc / Informe7508.lyx
index 02203080706ec8442344ba490fa14ed073b706b7..08b52c020129b2c927f76d2584a79d574d3195bd 100644 (file)
@@ -52,7 +52,7 @@ Leandro Lucarella (77891)
 Ricardo Markiewicz (78226)
 \layout Date
 
-Primera Entrega, 28 de Junio del 2004
+26 de Octubre del 2004
 \layout Standard
 
 
@@ -63,9 +63,6 @@ Primera Entrega, 28 de Junio del 2004
 
 \layout Chapter
 
-Desarollo e Implementación
-\layout Section
-
 Hipotesis y Aclaraciones
 \layout Itemize
 
@@ -73,7 +70,7 @@ El programa en su totalidad va a ser ejecutado por un 
  configuración diferente es posible pero queda en manos del administrador.
 \layout Itemize
 
-En los archivos de llamada se valida que sean numeros, y para validar la
+En los archivos de llamada se valida que sean números, y para validar la
  fecha no se tiene en cuenta casos particulares como el 29, 30, 31 de febrero.
 \layout Itemize
 
@@ -86,9 +83,24 @@ Aficonf utiliza n
  la acción.
 \layout Itemize
 
-El archivo de umbrales no puede ser modificado por el usuario manualmente,
- solo a travez de AFICONF
-\layout Section
+El instalador utiliza el archivo 
+\family typewriter 
+afinstal.conf
+\family default 
+, situado en el directorio 
+\family typewriter 
+$PATH_INSTALADOR/conf
+\family default 
+, para determinar que componentes se encuentran instalados.
+ Internamente, en base a la información de paths proporcionada por este
+ archivo, busca su los binarios realmente se encuentran en el OS, y en caso
+ contrario permite volver a reinstalarlo/s.
+\layout Chapter
+
+
+\begin_inset LatexCommand \label{sec:Problemas-relevantes}
+
+\end_inset 
 
 Problemas relevantes
 \layout Itemize
@@ -96,46 +108,130 @@ Problemas relevantes
 Dado que los distintos componentes del sistema se pueden instalar en diferentes
  paths dentro del OS, creamos el directorio 
 \family typewriter 
-$HOME/.antifraude
+~$HOME/.antifraude
 \family default 
  donde se almacenará información acerca de los paths en donde reside cada
- uno de ellos y otros archivos de intercambio y de rutinas comunes.
+ uno de ellos y otros archivos de intercambio.
 \layout Itemize
 
 Así mismo, como los programas pueden ser instalados en directorios distintos,
- toda la información compartida (oridesti.txt y umbrales.param) es guardada
- en 
+ toda la información compartida es guardada en 
 \family typewriter 
-$HOME/.antifraude
+~$HOME/.antifraude
 \family default 
 , para ser mas consistentes con la manera de trabajar en Unix.
  Lo ideal hubiera sido utilizar 
 \family typewriter 
 /etc/antifraude
 \family default 
-, pero como no podríamos suponer root access preferimos directamente trabajar
- en el home del usuario.
-\layout Section
+, pero como no podríamos suponer acceso de 
+\emph on 
+root
+\emph default 
+ preferimos directamente trabajar en el directorio del usuario.
+\layout Chapter
 
 Instalación
 \layout Standard
 
-Copiar del README cuando este terminado y extenderlo un poco si se considera
- necesario.
-\layout Section
-
-Comandos Desarrollados
-\layout Subsection
+Una vez descargados los fuentes (asumiremos que ha descargado el 
+\family typewriter 
+tar.gz
+\family default 
+) solo debe descomprimir el archivo ejecutando el siguiente comando:
+\layout LyX-Code
 
-AFIMONIO
+tar xvzf grupo12.tar.gz
 \layout Standard
 
+Esto creará la siguiente estructura de directorios:
+\layout LyX-Code
+
+./
+\layout LyX-Code
+
+ +- grupo12
+\layout LyX-Code
+
+ |
+\layout LyX-Code
+
+ +-- README
+\layout LyX-Code
+
+ +-- COPYING
+\layout LyX-Code
+
+ +-- afinstal
+\layout LyX-Code
+
+ +-- conf
+\layout LyX-Code
+
+ +---- umbrales.param
+\layout LyX-Code
+
+ +---- umbrales.id
+\layout LyX-Code
+
+ +---- oridesti.txt
+\layout LyX-Code
+
+ +-- inst
+\layout LyX-Code
+
+ +---- afimonio
+\layout LyX-Code
+
+ +---- antifraude.pl
+\layout LyX-Code
+
+ +---- aficonf
+\layout LyX-Code
+
+ +---- afimonio_daemon.sh
+\layout LyX-Code
+
+ +---- util.sh
+\layout LyX-Code
+
+ +---- callgen
+\layout LyX-Code
+
+ +---- testcalls.tar.gz
+\layout Standard
 
+Para proceder a la instalación del sistema 
 \series bold 
-Tipo de comando:
+antifraude
 \series default 
- Solicitado
-\layout Subsubsection
+ debe correr el script 
+\series bold 
+afinstal
+\series default 
+:
+\layout LyX-Code
+
+./afinstal
+\layout Standard
+
+y seguir los pasos que se le indiquen a continuación.
+ De no ejecutar apropiadamente la instalación, no se garantiza el correcto
+ funcionamiento de los componentes.
+\layout Chapter
+
+Comandos Desarrollados
+\layout Section
+
+AFIMONIO
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
 
 Archivos de Input
 \layout Standard
 \family default 
 \series medium 
  según corresponda.
-\layout Subsubsection
+\layout Subsection
 
 Archivos de Output
 \layout Standard
 
-El afimonio genera una salida al archivo afimonio.log la cual contiene informació
-n sobre la ejecución del programa.
+El afimonio genera una salida al archivo 
+\family typewriter 
+afimonio.log
+\family default 
+ la cual contiene información sobre la ejecución del programa.
 \layout Standard
 
 Si un archivo es válido, se añade una línea con el siguiente formato: 
-\layout Standard
+\layout LyX-Code
 
-"$fecha $USER afimonio: "Se detecta archivo de llamadas $file" 
+$fecha $USER afimonio: "Se detecta archivo de llamadas $file"
 \layout Standard
 
 Si el archivo tuviera un nombre inválido, la línea seria la siguiente: 
-\layout Standard
+\layout LyX-Code
 
-"$fecha $USER afimonio:"Se rechaza el archivo $file".
+$fecha $USER afimonio: "Se rechaza el archivo $file"
 \layout Standard
 
-donde 
-\layout Standard
+donde:
+\layout Description
 
-$fecha: fecha actual con formato Día-Mes-Año-Hora:Minuto.
-\layout Standard
 
-$USER: nombre de usuario que ejecuto el script.
+\family typewriter 
+$fecha
+\family default 
+ fecha actual con formato Día-Mes-Año-Hora:Minuto.
+\layout Description
+
+
+\family typewriter 
+$USER
+\family default 
+ nombre de usuario que ejecuto el script.
+\layout Description
+
+
+\family typewriter 
+$file
+\family default 
+ nombre del archivo que se procesó.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio
 \layout Standard
 
-$file: nombre del archivo que se procesó.
+Corre el programa en primer plano.
 \layout Subsubsection
 
-Ejemplos de invocación
+
+\family typewriter 
+nohup ./afimonio &
+\layout Standard
+
+Corre el programa en segundo plano, evitando que se cierre al morir el padre
+ desasociándolo de la terminal.
+ La salida del programa queda en el archivo 
+\family typewriter 
+nohup.out
+\family default 
+ a menos que se redirija a otro archivo.
+\layout Subsection
+
+Código Fuente
 \layout LyX-Code
 
-:afimonio/bin$> ./afimonio
+#!/bin/bash
 \layout LyX-Code
 
-:afimonio/bin$> nohup ./afimonio & 
 \layout LyX-Code
 
-:afimonio/bin$> ./afimonio_daemon.sh
+BASE_DIR=$HOME/.antifraude
 \layout LyX-Code
 
-    afimonio_daemon.sh (start|stop|status)
-\layout Subsubsection
+\layout LyX-Code
 
-Código Fuente
-\layout Standard
+# uso las funciones de util.sh
+\layout LyX-Code
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+.
+ "$HOME/.antifraude/util.sh"
+\layout LyX-Code
 
-ANTIFRAUDE
-\layout Standard
+.
+ "$HOME/.antifraude/conf/afimonio.conf"
+\layout LyX-Code
 
+.
+ "$HOME/.antifraude/conf/antifraude.conf"
+\layout LyX-Code
 
-\series bold 
-Tipo de comando:
-\series default 
- Solicitado
-\layout Subsubsection
+\layout LyX-Code
 
-Archivos de Input
-\layout Standard
+# Es llamada por los trap para deslockear el afimonio 
+\layout LyX-Code
 
-Procesa los archivos de llamadas que encuentre en el momento de invocación
- en el directorio 
-\family typewriter 
-$PATH_ANTIFRAUDE/$DATADIR/enproceso
-\family default 
-.
- El demonio 
-\series bold 
-Afimonio
-\series default 
- será quien alimentará al 
-\series bold 
-Antifraude
-\series default 
- con dichos archivos, no obstante se lo puede alimentar con archivos de
- llamadas en forma manual, situándolos en el directorio anteriormente descripto.
-\layout Subsubsection
+finalize() {
+\layout LyX-Code
 
-Archivos de Output
-\layout Itemize
+        unlock "afimonio" 
+\layout LyX-Code
 
+        exit 0
+\layout LyX-Code
 
-\series bold 
-Antifraude.log:
-\series default 
- Se loguea en este archivo el procesamiento de los registros, warnings provocado
-s por registros no validos y alarmas emitidas por registros que matchean
- contra un umbral.
-\layout Itemize
+}
+\layout LyX-Code
 
+# filtra el nombre del archivo pasado por parametro sacandole
+\layout LyX-Code
 
-\series bold 
-Alarmas.txt:
-\series default 
- Se loguean en este archivo las alarmas provocadas por registros en los
- archivos de llamadas, que hayan matcheado un umbral determinado del archivo
- umbrales.param.
-\layout Subsubsection
+# todos los caracteres que no sean numeros 
+\layout LyX-Code
 
-Ejemplos de invocación
+checkfilename(){
 \layout LyX-Code
 
-:antifraude/bin$> perl antifraude.pl
+        date=`echo $1 | cut -d "." -f 1`
 \layout LyX-Code
 
-:antifraude/bin$> perl antifraude.pl &
-\layout Subsubsection
+        central=`echo $1 | cut -d "." -f 2`
+\layout LyX-Code
 
-Código Fuente
-\layout Standard
+        validar_solo_numeros "$date"
+\layout LyX-Code
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
-AFICONF
-\layout Standard
+                return 1
+\layout LyX-Code
 
+        fi
+\layout LyX-Code
 
-\series bold 
-Tipo de comando:
-\series default 
- Solicitado
-\layout Subsubsection
+        mes=${date:4:2}
+\layout LyX-Code
 
-Archivos de Input
-\layout Standard
+        validar_rango "$mes" "1" "12"
+\layout LyX-Code
 
-El comando utiliza los archivos umbrales.param y oridesti.txt situados en
-\family typewriter 
-~$HOME/.antifraude/
-\layout Subsubsection
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
-Archivos de Output
-\layout Standard
+                return 1
+\layout LyX-Code
 
-Solo escribe en umbrales.param de ser solicitado por el usuario, ya sea por
- la alta o baja de un umbral.
-\layout Subsubsection
+        fi
+\layout LyX-Code
 
-Ejemplos de invocación
+        dia=${date:6:2}
 \layout LyX-Code
 
-:aficonf/bin$> ./aficonf
-\layout Subsubsection
+        validar_rango "$dia" "1" "31" 
+\layout LyX-Code
 
-Código Fuente
-\layout Standard
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+                return 1
+\layout LyX-Code
 
-CALLGEN
-\layout Standard
+        fi
+\layout LyX-Code
 
+        hora=${date:8:2}
+\layout LyX-Code
 
-\series bold 
-Tipo de comando:
-\series default 
- Auxiliar, escrito en PERL
-\layout Subsubsection
+        validar_rango "$hora" "0" "23"
+\layout LyX-Code
 
-Justificación de su uso
-\layout Standard
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
-Sirve para realizar lotes de prueba con gran cantidad de entradas y variaciones
- de forma rápida y cómoda.
-\layout Subsubsection
+                return 1
+\layout LyX-Code
 
-Archivos de Input
-\layout Standard
+        fi
+\layout LyX-Code
 
-Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
- redireccionarle el archivo 
-\family typewriter 
-oridesti.txt
-\family default 
-.
- De la entrada estándar toma los códigos de origen y destino.
- Cada código debe encontrarse en una línea y al comienzo de ésta.
- Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
- compatibilidad con el archivo oridesti.txt).
-\layout Subsubsection
+        min=${date:10:2}
+\layout LyX-Code
 
-Archivos de Output
-\layout Standard
+        validar_rango "$min" "0" "59"
+\layout LyX-Code
 
-Crea una cantidad N (especificada por el usuario) de archivos con nombre
- y formato de Archivo de Llamadas en el directorio actual.
- Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
-mente (respetando el formato mencionado y con valores racionales).
-\layout Subsubsection
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
 
-Parámetros
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        validar_solo_numeros "$central"
+\layout LyX-Code
+
+        if [ "$?" -ne 0 ]; then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        return 0                
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#--------------------MAIN SCRIPT----------------------
+\layout LyX-Code
+
+# Recupero las rutas a todos los directorios y archivos
+\layout LyX-Code
+
+# que necesito del antifraude
+\layout LyX-Code
+
+DATADIR=$ANTI_DATADIR
+\layout LyX-Code
+
+SOURCEDIR=$DATADIR/aprocesar/
+\layout LyX-Code
+
+ACEPTDIR=$DATADIR/enproceso/
+\layout LyX-Code
+
+REJECTDIR=$DATADIR/rechazadas/
+\layout LyX-Code
+
+BINDIR=$ANTI_BINDIR
+\layout LyX-Code
+
+# Del afimonio
+\layout LyX-Code
+
+LOGDIR=$AFIM_LOGDIR
+\layout LyX-Code
+
+LOGNAME=$AFIM_LOGFILE
+\layout LyX-Code
+
+LOGFILE=$LOGDIR/$LOGNAME
+\layout LyX-Code
+
+# Capturo señales para salir bien (liberando el lock)
+\layout LyX-Code
+
+trap "finalize" INT
+\layout LyX-Code
+
+trap "finalize" TERM 
+\layout LyX-Code
+
+# Me lockeo
+\layout LyX-Code
+
+lock "afimonio" || die "No se puede correr, hay otra 
+\backslash 
+
+\layout LyX-Code
+
+instancia corriendo o no se puede crear el lock file!"
+\layout LyX-Code
+
+# Comienza el ciclo infinito que mueve los archivos
+\layout LyX-Code
+
+while true; do 
+\layout LyX-Code
+
+        files=
+\layout LyX-Code
+
+        for file in `ls $SOURCEDIR` ; do
+\layout LyX-Code
+
+                files=1
+\layout LyX-Code
+
+                checkfilename $file     
+\layout LyX-Code
+
+                if [ "$?" -eq 0 ]; then
+\layout LyX-Code
+
+                        mv "$SOURCEDIR$file" "$ACEPTDIR"
+\layout LyX-Code
+
+                        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+                        echo "$fecha $USER afimonio:
+\backslash 
+"Se detecta " 
+\backslash 
+
+\layout LyX-Code
+
+                          "archivo de llamadas $file
+\backslash 
+"" >> $LOGFILE
+\layout LyX-Code
+
+                else 
+\layout LyX-Code
+
+                        mv "$SOURCEDIR$file" "$REJECTDIR"
+\layout LyX-Code
+
+                        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+                        echo "$fecha $USER afimonio:
+\backslash 
+"Se rechaza " 
+\backslash 
+
+\layout LyX-Code
+
+                          "el archivo $file
+\backslash 
+"" >> $LOGFILE
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                clean_log "$LOGFILE" "$AFIM_LOGSIZE"
+\layout LyX-Code
+
+        done #for
+\layout LyX-Code
+
+        # me fijo si el antifraude esta corriendo y si no lo esta
+\layout LyX-Code
+
+        # lo arranco
+\layout LyX-Code
+
+        if [ -n $files ] && ! is_lock "antifraude.pl"; then
+\layout LyX-Code
+
+                $BINDIR/antifraude.pl &
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        sleep 5
+\layout LyX-Code
+
+done #while
+\layout Section
+
+ANTIFRAUDE.PL
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Procesa los archivos de llamadas que encuentre en el momento de invocación
+ en el directorio 
+\family typewriter 
+$PATH_ANTIFRAUDE/$DATADIR/enproceso
+\family default 
+.
+ El demonio 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ será quien alimentará al 
+\family typewriter 
+\series bold 
+antifraude
+\family default 
+\series default 
+ con dichos archivos, no obstante se lo puede alimentar con archivos de
+ llamadas en forma manual, situándolos en el directorio anteriormente descripto.
+\layout Standard
+
+Este comando, en el momento de invocacion genera y guarda internamente un
+ listado de los archivos de llamadas presences en el directorio 
+\family typewriter 
+/enproceso
+\family default 
+, ordenándolos por fecha (establecida en el nombre del archivo) en forma
+ ascendente.
+ Dado que utiliza durante toda su ejecución esta lista interna, el 
+\family typewriter 
+\series bold 
+Afimonio
+\family default 
+\series default 
+ puede alimentar al directorio 
+\family typewriter 
+/enproceso
+\family default 
+ con nuevos archivos mientras el 
+\family typewriter 
+\series bold 
+Antifraude
+\family default 
+\series default 
+ corre, pero los mismos no serán tenidos en cuenta (esto es, procesados),
+ hasta la próxima invocación del comando.
+\layout Subsection
+
+Archivos de Output
+\layout Description
+
+
+\family typewriter 
+Antifraude.log
+\family default 
+ En este archivo se guarda información del procesamiento de los registros,
+ advertencias provocados por registros no validos y alarmas emitidas por
+ registros que cumplen con un umbral.
+\layout Description
+
+
+\family typewriter 
+Alarmas.txt
+\family default 
+ En este archivo se guarda información de las alarmas provocadas por registros
+ en los archivos de llamadas, que hayan cumplido un umbral determinado del
+ archivo 
+\family typewriter 
+umbrales.param
+\family default 
+.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./antifraude.pl
+\layout Standard
+
+El programa procesa las llamadas 
+\family typewriter 
+enproceso
+\family default 
+ como indica el enunciado en primer plano.
+\layout Subsubsection
+
+
+\family typewriter 
+perl antifraude.pl
+\layout Standard
+
+Ídem anterior.
+\layout Subsubsection
+
+
+\family typewriter 
+./antifraude.pl &
+\layout Standard
+
+Ídem anterior pero procesa en segundo plano.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/usr/bin/perl
+\layout LyX-Code
+
+sub is_lock {
+\layout LyX-Code
+
+        if ( -e "$ENV{'HOME'}/.antifraude/lock/antifraude.pid" ) {
+\layout LyX-Code
+
+                # Lock file encontrado
+\layout LyX-Code
+
+                return 1;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        # No hay lock file!
+\layout LyX-Code
+
+        return 0;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub unlock {
+\layout LyX-Code
+
+        unlink ("$ENV{'HOME'}/.antifraude/lock/antifraude.pid");
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub lock {
+\layout LyX-Code
+
+        if (!is_lock()) {
+\layout LyX-Code
+
+                local $lfile = "$ENV{'HOME'}/.antifraude/lock/antifraude.pid";
+\layout LyX-Code
+
+                open(LOCKFILE,">>$lfile");
+\layout LyX-Code
+
+                print LOCKFILE $$;
+\layout LyX-Code
+
+                close(LOCKFILE);
+\layout LyX-Code
+
+                return 1;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        return 0;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Comparador de fecha para los archivos de llamada
+\layout LyX-Code
+
+sub byDate {
+\layout LyX-Code
+
+        ($year1,$mon1,$day1,$hr1,$min1) =
+\layout LyX-Code
+
+          $a =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
+\layout LyX-Code
+
+        ($year2,$mon2,$day2,$hr2,$min2) =
+\layout LyX-Code
+
+          $b =~ /([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/;
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        # Descarto por año
+\layout LyX-Code
+
+        if ($year1 > $year2) { return 1; }
+\layout LyX-Code
+
+        elsif ($year1 < $year2) { return -1; }
+\layout LyX-Code
+
+        # Descarto por mes
+\layout LyX-Code
+
+        if ($mon1 > $mon2) { return 1; }
+\layout LyX-Code
+
+        elsif ($mon1 < $mon2) { return -1; }
+\layout LyX-Code
+
+        # Calculo minutos de lo restante
+\layout LyX-Code
+
+        $totalmin1 = ($day1 * 24 * 60) + ($hr1 * 60) + $min1;
+\layout LyX-Code
+
+        $totalmin2 = ($day2 * 24 * 60) + ($hr2 * 60) + $min2;
+\layout LyX-Code
+
+        if ($totalmin1 > $totalmin2) { return 1; }
+\layout LyX-Code
+
+        elsif ($totalmin1 < $totalmin2) { return -1; }
+\layout LyX-Code
+
+        else { return 0; }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Devuelve un listado de archivos de llamada y ordenado por fecha ASC
+\layout LyX-Code
+
+sub getCallFiles {
+\layout LyX-Code
+
+        # Obtengo listado de archivos de llamadas y lo ordeno por fecha
+\layout LyX-Code
+
+        opendir($DIR,"$CONFDATA{datadir}/enproceso")
+\layout LyX-Code
+
+          or die 'Could not open dir';
+\layout LyX-Code
+
+        # Valido solo fisicamente, lo logico ya valido afimonio..
+\layout LyX-Code
+
+        @files = grep {/[0-9]{12}
+\backslash 
+.[0-9]{4}$/
+\layout LyX-Code
+
+          && -f "$CONFDATA{datadir}/enproceso/$_"} readdir($DIR);
+\layout LyX-Code
+
+        @sortedfiles = sort byDate @files;
+\layout LyX-Code
+
+        closedir($DIR);
+\layout LyX-Code
+
+        return @sortedfiles;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Levanta una variable del archivo AFINSTAL.CONF
+\layout LyX-Code
+
+sub getConfVar {
+\layout LyX-Code
+
+        $CONFIGFILE = shift(@_);
+\layout LyX-Code
+
+        my $linenumber = shift(@_);
+\layout LyX-Code
+
+        open(CONFIGFILE)
+\layout LyX-Code
+
+          or die "No se pudo abrir el archivo $CONFIGFILE";
+\layout LyX-Code
+
+        do { $line = <CONFIGFILE> } until $.
+ == $linenumber;
+\layout LyX-Code
+
+        close(CONFIGFILE);
+\layout LyX-Code
+
+        chop($line);
+\layout LyX-Code
+
+        ($confvar = $line) =~ s/"(.*)"$/$1/;
+\layout LyX-Code
+
+        $confvar =~ s/^.*=//;
+\layout LyX-Code
+
+        return $confvar;
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Agrega un log entry al logfile del antifraude.pl
+\layout LyX-Code
+
+sub logEntry {
+\layout LyX-Code
+
+        my $logentry = shift(@_);
+\layout LyX-Code
+
+        my $consoleout = shift(@_);
+\layout LyX-Code
+
+        my $log = "$CONFDATA{logdir}/$CONFDATA{logfile}";
+\layout LyX-Code
+
+        # Fetch date and Format it
+\layout LyX-Code
+
+        ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
+\layout LyX-Code
+
+          = localtime(time);
+\layout LyX-Code
+
+        $mon =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $mday =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $hour =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $min =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+        $year += 1900; ++$mon;
+\layout LyX-Code
+
+        $user = "$ENV{USER}";
+\layout LyX-Code
+
+        $commonstring = "$mday/$mon/$year-$hour:$min $user antifraude:";
+\layout LyX-Code
+
+        # Append to log
+\layout LyX-Code
+
+        open(LOGFILE,">>$log")
+\layout LyX-Code
+
+          or die "No se pudo abrir el archivo de log";
+\layout LyX-Code
+
+        seek(LOGFILE,0,2);
+\layout LyX-Code
+
+        print LOGFILE "$commonstring 
+\backslash 
+"$logentry
+\backslash 
+"
+\backslash 
+n";
+\layout LyX-Code
+
+        $filesize = tell(LOGFILE);
+\layout LyX-Code
+
+        close(LOGFILE);
+\layout LyX-Code
+
+        # Chequeo el logsize y su lo supero me quedo con 100 lineas
+\layout LyX-Code
+
+        if ($filesize > $CONFDATA{logsize})
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                open(LOGFILE,"+<$log");
+\layout LyX-Code
+
+                do ($line = <LOGFILE>) until $.
+ == 100;
+\layout LyX-Code
+
+                truncate(LOGFILE,tell(LOGFILE));
+\layout LyX-Code
+
+                close(LOGFILE);
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        if ($consoleout) { print("$logentry
+\backslash 
+n"); }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub badCall {
+\layout LyX-Code
+
+        my $callreg = shift(@_);
+\layout LyX-Code
+
+        my $numreg = shift(@_);
+\layout LyX-Code
+
+        logEntry("El siguiente registro de llamada tiene format ".
+\layout LyX-Code
+
+          "o invalido
+\backslash 
+n$callreg",0);
+\layout LyX-Code
+
+        print("Warning: El registro de llamada $numreg tiene ".
+\layout LyX-Code
+
+          "formato invalido
+\backslash 
+n");
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+sub checkUmbrales {
+\layout LyX-Code
+
+        local(*callfields) = $_[0];
+\layout LyX-Code
+
+        my $callsfile = $_[1];
+\layout LyX-Code
+
+        my $matchedUmbral = 0;
+\layout LyX-Code
+
+        my $i = 0;
+\layout LyX-Code
+
+        while (($i <= $#UMBRALES) && ($matchedUmbral == 0)) {
+\layout LyX-Code
+
+                $umbral = $UMBRALES[$i];
+\layout LyX-Code
+
+                chomp($umbral);
+\layout LyX-Code
+
+                ($regid,$phoneline,$oridest,$type,$state)
+\layout LyX-Code
+
+                  = split(';',$umbral);
+\layout LyX-Code
+
+                if (($state eq 'A') && ($callfields[0] == $phoneline)
+\layout LyX-Code
+
+                  && ($callfields[4] eq $type)) {
+\layout LyX-Code
+
+                        # Si es Saliente y coincide el Destino con el
+\layout LyX-Code
+
+                        # Ori/Dest del umbral
+\layout LyX-Code
+
+                        if (($type eq 'S')
+\layout LyX-Code
+
+                          && ($callfields[5] eq $oridest)) {
+\layout LyX-Code
+
+                                $matchedUmbral = $regid;
+\layout LyX-Code
+
+                        }
+\layout LyX-Code
+
+                        if (($type eq 'E')
+\layout LyX-Code
+
+                          && ($callfields[6] eq $oridest)) {
+\layout LyX-Code
+
+                                $matchedUmbral = $regid;
+\layout LyX-Code
+
+                        }
+\layout LyX-Code
+
+                }                       
+\layout LyX-Code
+
+                ++$i;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        # Si se matcheo un umbral, grabo una alarma y aviso por consola
+\layout LyX-Code
+
+        if ($matchedUmbral > 0) {
+\layout LyX-Code
+
+                # Obtengo algunos datos
+\layout LyX-Code
+
+                ($central = $callsfile) =~ s/^.*
+\backslash 
+.//;
+\layout LyX-Code
+
+                $user = "$ENV{USER}";
+\layout LyX-Code
+
+                # Fetch date and Format it
+\layout LyX-Code
+
+                ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
+\layout LyX-Code
+
+                  = localtime(time);
+\layout LyX-Code
+
+                $year += 1900; ++$mon;
+\layout LyX-Code
+
+                $mon =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $mday =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $hour =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $min =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $sec =~ s/^(
+\backslash 
+d)$/0$1/;
+\layout LyX-Code
+
+                $user = "$ENV{USER}";
+\layout LyX-Code
+
+                $date = "${year}${mon}${mday}";
+\layout LyX-Code
+
+                $time = "${hour}${min}${sec}";
+\layout LyX-Code
+
+                # Preparo el registro de alarma
+\layout LyX-Code
+
+                $alarmEntry = "$callfields[7];$central;$callfields[0];".
+\layout LyX-Code
+
+                  "$callfields[1];$regid;$callfields[2];".
+\layout LyX-Code
+
+                  "$callfields[3];$user;$date;$time";
+\layout LyX-Code
+
+                # Grabamos el registro en el archivo de alarmas
+\layout LyX-Code
+
+                $alarmlog = "$CONFDATA{datadir}/alarmas/alarmas.txt";
+\layout LyX-Code
+
+                open(ALARMFILE,">>$alarmlog")
+\layout LyX-Code
+
+                  or die 'No se pudo abrir el archivo de alarmas';
+\layout LyX-Code
+
+                seek(ALARMFILE,0,2);
+\layout LyX-Code
+
+                print ALARMFILE "$alarmEntry
+\backslash 
+n";
+\layout LyX-Code
+
+                close(ALARMFILE);
+\layout LyX-Code
+
+                # Logeo por consola y logfile que hubo una alarma
+\layout LyX-Code
+
+                logEntry("Alarma: Se ha matcheado el registro procesado"
+\layout LyX-Code
+
+                  ." con el umbral nro $matchedUmbral",1);
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# --------- MAIN CODE -------- #
+\layout LyX-Code
+
+# File locking..
+\layout LyX-Code
+
+if (is_lock()) { exit 1; }
+\layout LyX-Code
+
+lock();
+\layout LyX-Code
+
+# Defino some GLOBALS
+\layout LyX-Code
+
+$CONFDIR = "$ENV{'HOME'}/.antifraude";
+\layout LyX-Code
+
+$CONFDATA{logdir} = getConfVar("$CONFDIR/conf/antifraude.conf",2);
+\layout LyX-Code
+
+$CONFDATA{logfile} = getConfVar("$CONFDIR/conf/antifraude.conf",3);
+\layout LyX-Code
+
+$CONFDATA{logsize} = getConfVar("$CONFDIR/conf/antifraude.conf",4);
+\layout LyX-Code
+
+$CONFDATA{datadir} = getConfVar("$CONFDIR/conf/antifraude.conf",5);
+\layout LyX-Code
+
+# Cargo los UMBRALES en memoria
+\layout LyX-Code
+
+open(PARAMFILE,"$CONFDIR/umbrales.param") or die "No se pudo abrir el "
+\layout LyX-Code
+
+  ."archivo de umbrales";
+\layout LyX-Code
+
+@UMBRALES = <PARAMFILE>;
+\layout LyX-Code
+
+close(PARAMFILE);
+\layout LyX-Code
+
+# Proceso los archivos de llamadas
+\layout LyX-Code
+
+@archivos = getCallFiles();
+\layout LyX-Code
+
+FILE: foreach $filename (@archivos) {
+\layout LyX-Code
+
+        $regnum = 0;
+\layout LyX-Code
+
+        $CALLFILE = "$CONFDATA{datadir}/enproceso/$filename";
+\layout LyX-Code
+
+        logEntry("Inicio proceso de: $filename",1);
+\layout LyX-Code
+
+        open(CALLFILE)
+\layout LyX-Code
+
+          or ((warn "No se pudo abrir archivo $filename"),next FILE);
+\layout LyX-Code
+
+        REG: foreach $callreg (<CALLFILE>) {
+\layout LyX-Code
+
+                logEntry("Procesando Reg: $regnum | Archivo: $filename",1);
+\layout LyX-Code
+
+                chomp($callreg);
+\layout LyX-Code
+
+                $fieldcount = split(';',$callreg);
+\layout LyX-Code
+
+                @fields = @_;
+\layout LyX-Code
+
+                # Si no tengo 8 campos exactamente, invalido
+\layout LyX-Code
+
+                if ($fieldcount != 8)
+\layout LyX-Code
+
+                {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum);
+\layout LyX-Code
+
+                        next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Si la linea no es un numero, invalido
+\layout LyX-Code
+
+                $fields[0] =~ s/^
+\backslash 
+s*(
+\backslash 
+w*)
+\backslash 
+s*$/$1/;
+\layout LyX-Code
+
+                if (!($fields[0] =~ /^
+\backslash 
+d+$/))
+\layout LyX-Code
+
+                {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum);
+\layout LyX-Code
+
+                        next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Si tipo llamada ! E|S o no se informa Origen
+\layout LyX-Code
+
+                # o Destino, invalido
+\layout LyX-Code
+
+                if (($fields[4] ne 'E') && ($fields[4] ne 'S')) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                if (($fields[4] eq 'E') && ($fields[6] eq "")) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                if (($fields[4] eq 'S') && ($fields[5] eq "")) {
+\layout LyX-Code
+
+                        badCall($callreg,$regnum); next REG;
+\layout LyX-Code
+
+                }
+\layout LyX-Code
+
+                # Ya pase todas las validaciones, ahora busco si
+\layout LyX-Code
+
+                # exite un umbral
+\layout LyX-Code
+
+                checkUmbrales(*fields,$filename);
+\layout LyX-Code
+
+        } continue { ++$regnum }
+\layout LyX-Code
+
+        close(CALLFILE);
+\layout LyX-Code
+
+        # La muevo al directorio de procesadas
+\layout LyX-Code
+
+        rename $CALLFILE,"$CONFDATA{datadir}/procesadas/$filename";
+\layout LyX-Code
+
+        logEntry("Fin proceso de: $filename",1);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+# Unlocking
+\layout LyX-Code
+
+unlock();
+\layout Section
+
+AFICONF
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Solicitado.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+El comando utiliza los archivos 
+\family typewriter 
+umbrales.param
+\family default 
+ y 
+\family typewriter 
+oridesti.txt
+\family default 
+ situados en 
+\family typewriter 
+~$HOME/.antifraude/
+\layout Subsubsection
+
+Archivos de Output
+\layout Standard
+
+Solo escribe en 
+\family typewriter 
+umbrales.param
+\family default 
+ de ser solicitado por el usuario, ya sea por la alta o baja de un umbral.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./aficonf
+\layout Standard
+
+Realiza lo pedido en el enunciado.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/bin/sh
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Configurador
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo config
+\layout LyX-Code
+
+BASE_DIR="$HOME/.antifraude"
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo config
+\layout LyX-Code
+
+.
+ "$BASE_DIR/conf/aficonf.conf"
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Cargo utilidades
+\layout LyX-Code
+
+.
+ "$BASE_DIR/util.sh"
+\layout LyX-Code
+
+LOGDIR=$AFIC_LOGDIR
+\layout LyX-Code
+
+LOGNAME=$AFIC_LOGFILE
+\layout LyX-Code
+
+LOGFILE=$LOGDIR/$LOGNAME
+\layout LyX-Code
+
+\layout LyX-Code
+
+#Valida que exista el pais
+\layout LyX-Code
+
+# Parámetros :
+\layout LyX-Code
+
+#   $1 = Descripcion a buscar
+\layout LyX-Code
+
+#   $2 = Variable donde guardar el código del Pais
+\layout LyX-Code
+
+#        en caso de existir
+\layout LyX-Code
+
+existe_pais () {
+\layout LyX-Code
+
+        EXISTE=`cat "$BASE_DIR/oridesti.txt" 
+\backslash 
+
+\layout LyX-Code
+
+          | egrep "^[A-Z]*;$1" | cut -d ';' -f 1`;
+\layout LyX-Code
+
+        if [ "$EXISTE" != "" ] ; then
+\layout LyX-Code
+
+                #Exite!, debo gaurdar el código
+\layout LyX-Code
+
+                eval "$2=$EXISTE"
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+poner_estado_umbral () {
+\layout LyX-Code
+
+        ID=$1
+\layout LyX-Code
+
+        ESTADO=$2
+\layout LyX-Code
+
+        FECHA=`date +"%Y%m%d"`
+\layout LyX-Code
+
+        HORA=`date +"%H%M%S"`
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        if [ "$ESTADO" != "A" ] && [ "$ESTADO" != "I" ]
+\layout LyX-Code
+
+        then
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        SALIDA=`sed "s/^$ID
+\backslash 
+(;[^;]*;[^;]*;[^;]*;
+\backslash 
+)[^;]*
+\backslash 
+(;"
+\backslash 
+
+\layout LyX-Code
+
+"[^;]*;[^;]*;[^;]*
+\backslash 
+)$/$ID
+\backslash 
+1I;$USER;$FECHA;$HORA/" 
+\backslash 
+
+\layout LyX-Code
+
+          "$BASE_DIR/umbrales.param"`
+\layout LyX-Code
+
+        echo "$SALIDA" > "$BASE_DIR/umbrales.param"
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "Se ha cambiado el estado de umbral $ID a $ESTADO" 
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+menu () {
+\layout LyX-Code
+
+        echo "AFICONF"
+\layout LyX-Code
+
+        echo "======="
+\layout LyX-Code
+
+        echo
+\layout LyX-Code
+
+        echo "  1) Alta"
+\layout LyX-Code
+
+        echo "  2) Buscar"
+\layout LyX-Code
+
+        echo "  3) Salir"
+\layout LyX-Code
+
+        preguntar "Su opción" "123" $1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+existe_umbral () {
+\layout LyX-Code
+
+        EXISTE=`cat "$BASE_DIR/umbrales.param" | egrep "$1"`;
+\layout LyX-Code
+
+        if [ "$EXISTE" == "" ] ; then
+\layout LyX-Code
+
+                #No existe
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        #Ya existe un umbral!
+\layout LyX-Code
+
+        return 0
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+buscar_id_umbral () {
+\layout LyX-Code
+
+        ID=`cat "$BASE_DIR/umbrales.id"`;
+\layout LyX-Code
+
+        eval "$1=$ID"
+\layout LyX-Code
+
+        let ID=$ID+1
+\layout LyX-Code
+
+        echo "$ID" > "$BASE_DIR/umbrales.id"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+case_altas () {
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Número de línea" "" LINEA
+\layout LyX-Code
+
+                #TODO Valido
+\layout LyX-Code
+
+                if ! validar_solo_numeros "$LINEA" ; then
+\layout LyX-Code
+
+                        echo "EL NUMERO TE LINEA SOLO DEBE" 
+\backslash 
+
+\layout LyX-Code
+
+                        "TENER DIGITOS"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$LINEA" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        preguntar "Tipo de llamada" "ES" TIPO
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        CODIGO=''
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Pais (descripción)" "" PAIS 
+\layout LyX-Code
+
+                if ! existe_pais "$PAIS" CODIGO ; then
+\layout LyX-Code
+
+                        echo "No existe el país de descrición '$PAIS'"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$PAIS" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        echo "El código de '$PAIS' es '$CODIGO'"
+\layout LyX-Code
+
+        PAIS=$CODIGO
+\layout LyX-Code
+
+        # Verifico que el umbral no exista
+\layout LyX-Code
+
+        FECHA=`date +"%Y%m%d"`
+\layout LyX-Code
+
+        HORA=`date +"%H%M%S"`
+\layout LyX-Code
+
+        UMBRAL="$LINEA;$PAIS;$TIPO;A;*;*;*"
+\layout LyX-Code
+
+        if existe_umbral "$UMBRAL" ; then
+\layout LyX-Code
+
+                echo "Ya existe un umbral con los datos ingresados."
+\layout LyX-Code
+
+                echo "Abortando..."
+\layout LyX-Code
+
+                put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+                  "Se trató de insertar un umbral repetido ($UMBRAL)" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+                return
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        
+\layout LyX-Code
+
+        # Genero el umbral
+\layout LyX-Code
+
+        buscar_id_umbral ID
+\layout LyX-Code
+
+        UMBRAL="$ID;$LINEA;$PAIS;$TIPO;A;$USER;$FECHA;$HORA"
+\layout LyX-Code
+
+        # Lo guardo
+\layout LyX-Code
+
+        echo "$UMBRAL" >> "$BASE_DIR/umbrales.param"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "El Umbral fue grabado con éxito"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        put_log "$LOGFILE" 
+\backslash 
+
+\layout LyX-Code
+
+          "aficonf" "Se inserto un nuevo umbral ($UMBRAL)" 
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+case_buscar () {
+\layout LyX-Code
+
+        DONE=0
+\layout LyX-Code
+
+        while [ $DONE == 0 ] ; do
+\layout LyX-Code
+
+                leer "Número de línea" "" LINEA
+\layout LyX-Code
+
+                #TODO Valido
+\layout LyX-Code
+
+                if ! validar_solo_numeros "$LINEA" ; then
+\layout LyX-Code
+
+                        echo "EL NUMERO TE LINEA SOLO DEBE" 
+\backslash 
+
+\layout LyX-Code
+
+                          "TENER DIGITOS"
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        DONE=1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                if [ "$LINEA" == "" ] ; then
+\layout LyX-Code
+
+                        DONE=0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        DATOS=`cat "$BASE_DIR/umbrales.param" 
+\backslash 
+
+\layout LyX-Code
+
+          | grep "[0-9]*;$LINEA;[A-Z]*;[E,S];A"`
+\layout LyX-Code
+
+        if [ "$DATOS" == "" ] ; then
+\layout LyX-Code
+
+                echo ""
+\layout LyX-Code
+
+                echo "No se han encontrado Umbrales activos" 
+\backslash 
+
+\layout LyX-Code
+
+                  "para la linea $LINEA."
+\layout LyX-Code
+
+                echo "Abortando ..."
+\layout LyX-Code
+
+                echo ""
+\layout LyX-Code
+
+                put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+                  "No se han encontrado umbrales para la línea $LINEA" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        printf "%3s      %2s  %1s   %1s    %10s%8s       %6s
+\backslash 
+n" 
+\backslash 
+
+\layout LyX-Code
+
+          "ID" "Ciudad" "Tipo" "Estado" "Usuario" "Fecha" "Hora"
+\layout LyX-Code
+
+        OPCIONES="-1"
+\layout LyX-Code
+
+        for i in $DATOS ; do
+\layout LyX-Code
+
+                ID=`echo "$i" | cut -d ';' -f 1`
+\layout LyX-Code
+
+                CIUDAD=`echo "$i" | cut -d ';' -f 3`
+\layout LyX-Code
+
+                TIPO=`echo "$i" | cut -d ';' -f 4`
+\layout LyX-Code
+
+                ESTADO=`echo "$i" | cut -d ';' -f 5`
+\layout LyX-Code
+
+                USUARIO=`echo "$i" | cut -d ';' -f 6`
+\layout LyX-Code
+
+                FECHA=`echo "$i" | cut -d ';' -f 7`
+\layout LyX-Code
+
+                HORA=`echo "$i" | cut -d ';' -f 8`
+\layout LyX-Code
+
+                printf 
+\backslash 
+
+\layout LyX-Code
+
+"%3s      %2s      %1s      %1s      %10s      %8s      %6s
+\backslash 
+n" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$ID" "$CIUDAD" "$TIPO" "$ESTADO" "$USUARIO" 
+\backslash 
+
+\layout LyX-Code
+
+                  "$FECHA" "$HORA"
+\layout LyX-Code
+
+                OPCIONES="$OPCIONES $ID"
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+        preguntar "Cual desea borrar (-1 para salir)" "$OPCIONES" OPT
+\layout LyX-Code
+
+        if [ "$OPT" = "-1" ] ; then
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        echo "Borrando el registro $OPT ..."
+\layout LyX-Code
+
+        poner_estado_umbral "$OPT" "I"
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "No se ha eliminado elumbral de ID $OPT" "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "El Umbral fue eliminado con éxito"
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# No permito correr 2 instancias de AFICONF
+\layout LyX-Code
+
+if is_lock "aficonf" ; then
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        echo "Aficonf está corriendo actualmente."
+\layout LyX-Code
+
+        echo ""
+\layout LyX-Code
+
+        put_log "$LOGFILE" "aficonf" 
+\backslash 
+
+\layout LyX-Code
+
+          "Se ha intentado ejecutar aficonf cuando este estaba corriendo"
+\backslash 
+
+\layout LyX-Code
+
+          "$AFIC_LOGSIZE"
+\layout LyX-Code
+
+        exit 1
+\layout LyX-Code
+
+fi
+\layout LyX-Code
+
+lock "aficonf"
+\layout LyX-Code
+
+# Loop Principal
+\layout LyX-Code
+
+OPT="0"
+\layout LyX-Code
+
+while [ "$OPT" != "3" ] ; do 
+\layout LyX-Code
+
+        menu OPT
+\layout LyX-Code
+
+        case $OPT in
+\layout LyX-Code
+
+                "1") case_altas ;;
+\layout LyX-Code
+
+                "2") case_buscar ;;
+\layout LyX-Code
+
+        esac
+\layout LyX-Code
+
+done
+\layout LyX-Code
+
+unlock "aficonf"
+\layout Section
+
+UTIL.SH
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en bash.
+\layout Standard
+
+Sería equivalente a una biblioteca compartida, no es exactamente un comando
+ que se pueda ejecutar directamente sino que se incluye desde otros comandos.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Es un archivo con varias funciones generales, sirve para no duplicar código
+ común entre los varios scripts de bash.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Al ser de propósito general, no tiene ningún archivo de input específico,
+ aunque hay funciones que utilizan archivos, no se describen aquí sino en
+ los comandos que usan este archivo.
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+Al no ser un comando ejecutable, no aplica.
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Standard
+
+Ídem anterior.
+\layout Subsection
+
+Código fuente
+\layout LyX-Code
+
+#/bin/bash
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Los scrips que incluyan deben definir BASE_DIR
+\layout LyX-Code
+
+# antes de incluirme!
+\layout LyX-Code
+
+\layout LyX-Code
+
+LOCK_DIR="$BASE_DIR/lock"
+\layout LyX-Code
+
+# Lee del teclado un valor
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# parámetros :
+\layout LyX-Code
+
+#  $1 = Leyeda a mostrar de pregunta
+\layout LyX-Code
+
+#  $2 = Valor default por si el usuario no ingresa nada
+\layout LyX-Code
+
+#  $3 = Variable donde guardar el valor ingresado (o el default)
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+leer () {
+\layout LyX-Code
+
+        MSG=$1
+\layout LyX-Code
+
+        DEFAULT=$2
+\layout LyX-Code
+
+        read -p "$MSG [$DEFAULT] : " ALGO 
+\layout LyX-Code
+
+        # Si el usuario no ingresa nada
+\layout LyX-Code
+
+        # nos quedamos con el valor default
+\layout LyX-Code
+
+        if [ ! -z "$ALGO" ] ; then
+\layout LyX-Code
+
+                eval "$3=$ALGO"
+\layout LyX-Code
+
+        else
+\layout LyX-Code
+
+                eval "$3=$DEFAULT"
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Realiza una pregunta al usuario
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# parámetros :
+\layout LyX-Code
+
+#  $1 = Leyeda a mostrar de preguntar
+\layout LyX-Code
+
+#  $2 = string con las opciones validas
+\layout LyX-Code
+
+#  $3 = Variable donde guardar el valor ingresado
+\layout LyX-Code
+
+#  $4 = Valor por defecto si se apreta ENTER
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+preguntar () {
+\layout LyX-Code
+
+        PREGUNTA="$1"
+\layout LyX-Code
+
+        OPCIONES="$2"
+\layout LyX-Code
+
+        DEFAULT="$4"
+\layout LyX-Code
+
+        while true; do
+\layout LyX-Code
+
+                read -p "$PREGUNTA [$OPCIONES]: " RTA
+\layout LyX-Code
+
+                # Si me pasaron un default y la respuesta es vacía
+\layout LyX-Code
+
+                if [ -n "$DEFAULT" -a -z "$RTA" ]; then
+\layout LyX-Code
+
+                        # devuelvo default
+\layout LyX-Code
+
+                        RTA="$DEFAULT"
+\layout LyX-Code
+
+                        return 0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                # Escapeo el caracter '-' por '
+\backslash 
+-'
+\layout LyX-Code
+
+                RTA=$(echo $RTA | sed "s/
+\backslash 
+-/
+\backslash 
+
+\backslash 
+
+\backslash 
+-/")
+\layout LyX-Code
+
+                IS_OK=`echo "$OPCIONES" | grep "$RTA"`
+\layout LyX-Code
+
+                if [ ! -z "$IS_OK" ] && [ ! -z "$RTA" ] ; then
+\layout LyX-Code
+
+                        eval "$3=$RTA"
+\layout LyX-Code
+
+                        return 0
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        done
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+validar_solo_numeros () {
+\layout LyX-Code
+
+        TEST=`echo "$1" | sed "s/[0-9]*//g"`
+\layout LyX-Code
+
+        if [ "$TEST" == "" ] ; then
+\layout LyX-Code
+
+                #Ok, son solo numeros
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        # ups, hay algo que no es un numero
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Crea un archivo de lock para un script
+\layout LyX-Code
+
+# Devuelve: 0 si ok, 1 si ya esta lockeado, 2 si no pudo crear lock.
+\layout LyX-Code
+
+# Uso: lock programa
+\layout LyX-Code
+
+lock () {
+\layout LyX-Code
+
+        # si ya esta loqueado, no lo vuelvo a crear
+\layout LyX-Code
+
+        is_lock "$1" && return 1
+\layout LyX-Code
+
+        # Si no puedo escribir en el dir de lock, da error
+\layout LyX-Code
+
+        [ -w "$LOCK_DIR" ] || return 2
+\layout LyX-Code
+
+        echo $$ > "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+        return 0
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Desbloquea el script
+\layout LyX-Code
+
+# Uso: unlock programa
+\layout LyX-Code
+
+unlock () {
+\layout LyX-Code
+
+        rm -rf "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+                        
+\layout LyX-Code
+
+# Consulta si un script esta lockeado
+\layout LyX-Code
+
+# Uso: is_lock programa
+\layout LyX-Code
+
+is_lock () {
+\layout LyX-Code
+
+        if [ -e "$LOCK_DIR/$1.pid" ] ; then
+\layout LyX-Code
+
+                # Lock file encontrado!
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+        # No hay lock file!
+\layout LyX-Code
+
+        return 1
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Obtiene el pid de un programa lockeado
+\layout LyX-Code
+
+# Uso: lock_pid programa
+\layout LyX-Code
+
+lock_pid()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        is_lock "$1" && cat "$LOCK_DIR/$1.pid"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Verifica que un valor este entre otros 2
+\layout LyX-Code
+
+# $1 pertecezca a [$2,$3]
+\layout LyX-Code
+
+# $1 Numero a validar
+\layout LyX-Code
+
+# $2 Cota inferior 
+\layout LyX-Code
+
+# $3 Cota superior
+\layout LyX-Code
+
+validar_rango(){
+\layout LyX-Code
+
+        if [ "$1" -ge "$2" ] && [ "$1" -le "$3" ]; then
+\layout LyX-Code
+
+                return 0
+\layout LyX-Code
+
+        else 
+\layout LyX-Code
+
+                return 1
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Muestra mensaje y sale con código de error
+\layout LyX-Code
+
+# Uso: die mensaje [código de error = 1]
+\layout LyX-Code
+
+die()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        echo "$1" >&2
+\layout LyX-Code
+
+        exit ${2:-1}
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Imprime mensaje por salida de error
+\layout LyX-Code
+
+# Uso: perr mensajes
+\layout LyX-Code
+
+perr()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        echo $@ >&2
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Pone un MSG en el log
+\layout LyX-Code
+
+# Parametros :
+\layout LyX-Code
+
+#  $1 = Archivo del log
+\layout LyX-Code
+
+#  $2 = Comando
+\layout LyX-Code
+
+#  $3 = Mensaje
+\layout LyX-Code
+
+#  $4 = Tamaño maximo
+\layout LyX-Code
+
+put_log() {
+\layout LyX-Code
+
+        fecha=$(date +%d/%m/%Y-%H:%M)
+\layout LyX-Code
+
+        echo "$fecha $USER $2:
+\backslash 
+"$3
+\backslash 
+"" >> $1
+\layout LyX-Code
+
+        clean_log "$1" "$4"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Trunca un archivo de log si pasa el tamaño máximo.
+\layout LyX-Code
+
+# Uso: clean_log log_filename max_log_size_bytes
+\layout LyX-Code
+
+clean_log()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        LOGFILE="$1"
+\layout LyX-Code
+
+        LOGSIZE="$2"
+\layout LyX-Code
+
+        # Archivo temporal
+\layout LyX-Code
+
+        tmp=`dirname "$LOGFILE"`"/`basename $0`.$$.temp"
+\layout LyX-Code
+
+        # Verifico que el logfile no se pase del tamaño maximo
+\layout LyX-Code
+
+        tam=`stat -c '%s' "$LOGFILE"`
+\layout LyX-Code
+
+        # Si se paso del maximo dejo las ultimas 100 lineas
+\layout LyX-Code
+
+        if [ "$tam" -ge "$LOGSIZE" ]; then
+\layout LyX-Code
+
+                tail -n 100 "$LOGFILE" > "$tmp"
+\layout LyX-Code
+
+                mv "$tmp" "$LOGFILE"
+\layout LyX-Code
+
+        fi
+\layout LyX-Code
+
+}
+\layout Section
+
+AFIMONIO_DAEMON.SH
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en 
+\family typewriter 
+bash
+\family default 
+.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Sirve para correr 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ en segundo plano, desasociado de la terminal.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
+ redireccionarle el archivo 
+\family typewriter 
+oridesti.txt
+\family default 
+.
+ De la entrada estándar toma los códigos de origen y destino.
+ Cada código debe encontrarse en una línea y al comienzo de ésta.
+ Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
+ compatibilidad con el archivo oridesti.txt).
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Crea una cantidad 
+\family typewriter 
+N
+\family default 
+ (especificada por el usuario) de archivos con nombre y formato de 
+\emph on 
+Archivo de Llamadas
+\emph default 
+ en el directorio actual.
+ Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
+mente (respetando el formato mencionado y con valores racionales).
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+La invocación es al estilo SysV, tomando como parámetro la acción a realizar,
+ que puede ser:
+\layout Description
+
+start Arranca el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Description
+
+stop Detiene el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Description
+
+status Indica si 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ está corriendo o no.
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Al comienzo del script, abajo de 
+\family typewriter 
+Configuración
+\family default 
+, se pueden cambiar algunas variables:
+\layout Description
+
+WAIT Cantidad de segundos a esperar para que arranque o se detenga 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ antes de asumir un error.
+\layout Description
+
+DAEMON Nombre del programa a ejecutar.
+ Este programa es lo suficientemente genérico como para correr cualquier
+ comando en modo 
+\emph on 
+daemon
+\emph default 
+, por eso se provee una variable de configuración para cambiar el comando
+ a ejecutar.
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh start
+\layout Standard
+
+Arranca el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh stop
+\layout Standard
+
+Detiene el 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh status
+\layout Standard
+
+Si 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+ está corriendo lo indica con un mensaje y muestra su PID.
+ Si no está corriendo da otro mensaje indicándolo.
+\layout Subsubsection
+
+
+\family typewriter 
+./afimonio_daemon.sh
+\layout Standard
+
+Da un mensaje de ayuda.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/bin/bash
+\layout LyX-Code
+
+\layout LyX-Code
+
+# Configuración
+\layout LyX-Code
+
+WAIT=10
+\layout LyX-Code
+
+DAEMON=afimonio
+\layout LyX-Code
+
+\layout LyX-Code
+
+# --------------- SCRIPT ---------------------
+\layout LyX-Code
+
+BASE_DIR="$HOME/.antifraude"
+\layout LyX-Code
+
+.
+ "$BASE_DIR/conf/$DAEMON.conf"
+\layout LyX-Code
+
+.
+ "$BASE_DIR/util.sh"
+\layout LyX-Code
+
+\layout LyX-Code
+
+ayuda () {
+\layout LyX-Code
+
+        perr "Parámetros válidos : start, stop, status"
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+\layout LyX-Code
+
+case "$1" in
+\layout LyX-Code
+
+        "start")
+\layout LyX-Code
+
+                echo -n "Iniciando demonio '$DAEMON' en modo daemon "
+\layout LyX-Code
+
+                if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo " ERROR!"
+\layout LyX-Code
+
+                        perr "$DAEMON ya está corriendo" 
+\backslash 
+
+\layout LyX-Code
+
+                             "(PID=`lock_pid $DAEMON`)."
+\layout LyX-Code
+
+                        exit 1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                nohup "$AFIM_BINDIR/$DAEMON" > /dev/null &
+\layout LyX-Code
+
+                for i in `seq $WAIT`; do
+\layout LyX-Code
+
+                        if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                                echo " OK! (PID=`lock_pid $DAEMON`)"
+\layout LyX-Code
+
+                                exit 0
+\layout LyX-Code
+
+                        fi
+\layout LyX-Code
+
+                        echo -n '.'
+\layout LyX-Code
+
+                        sleep 1;
+\layout LyX-Code
+
+                done
+\layout LyX-Code
+
+                # Tardó más de 5 segundos en arrancar, algo anda mal...
+\layout LyX-Code
+
+                echo "ERROR!"
+\layout LyX-Code
+
+                perr "$DAEMON tardó más de $WAIT segundos en arrancar,"
+\backslash 
+
+\layout LyX-Code
+
+                     "probablemente haya algún problema."
+\layout LyX-Code
+
+                exit 1
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        "stop")
+\layout LyX-Code
+
+                echo -n "Parando el demonio '$DAEMON' "
+\layout LyX-Code
+
+                if ! is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo " ERROR!"
+\layout LyX-Code
+
+                        perr "$DAEMON no esta corriendo."
+\layout LyX-Code
+
+                        exit 1
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+                kill `lock_pid $DAEMON`
+\layout LyX-Code
+
+                for i in `seq $WAIT`; do
+\layout LyX-Code
+
+                        if ! is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                                echo " OK!"
+\layout LyX-Code
+
+                                exit 0
+\layout LyX-Code
+
+                        fi
+\layout LyX-Code
+
+                        echo -n '.'
+\layout LyX-Code
+
+                        sleep 1;
+\layout LyX-Code
+
+                done
+\layout LyX-Code
+
+                # Tardó más de 5 segundos en parar, algo anda mal...
+\layout LyX-Code
+
+                echo "ERROR!"
+\layout LyX-Code
+
+                perr "$DAEMON tardó más de $WAIT segundos en parar," 
+\backslash 
+
+\layout LyX-Code
+
+                     "probablemente haya algún problema."
+\layout LyX-Code
+
+                exit 1
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        "status")
+\layout LyX-Code
+
+                if is_lock "$DAEMON"; then
+\layout LyX-Code
+
+                        echo "$DAEMON está corriendo actualmente" 
+\backslash 
+
+\layout LyX-Code
+
+                             "(PID=`lock_pid $DAEMON`)."
+\layout LyX-Code
+
+                else
+\layout LyX-Code
+
+                        echo "$DAEMON no está corriendo."
+\layout LyX-Code
+
+                fi
+\layout LyX-Code
+
+        ;;
+\layout LyX-Code
+
+        *) ayuda ;;
+\layout LyX-Code
+
+esac
+\layout Section
+
+CALLGEN
+\layout Subsection
+
+Tipo de comando
+\layout Standard
+
+Auxiliar, escrito en 
+\family typewriter 
+perl
+\family default 
+.
+\layout Subsection
+
+Justificación de su uso
+\layout Standard
+
+Sirve para realizar lotes de prueba con gran cantidad de entradas y variaciones
+ de forma rápida y cómoda.
+\layout Subsection
+
+Archivos de Input
+\layout Standard
+
+Ninguno, toma los datos necesarios por la entrada estándar, aunque es común
+ redireccionarle el archivo 
+\family typewriter 
+oridesti.txt
+\family default 
+.
+ De la entrada estándar toma los códigos de origen y destino.
+ Cada código debe encontrarse en una línea y al comienzo de ésta.
+ Sólo toma los 2 primeros caracteres, e ignora el resto de la línea (para
+ compatibilidad con el archivo oridesti.txt).
+\layout Subsection
+
+Archivos de Output
+\layout Standard
+
+Crea una cantidad 
+\family typewriter 
+N
+\family default 
+ (especificada por el usuario) de archivos con nombre y formato de 
+\emph on 
+Archivo de Llamadas
+\emph default 
+ en el directorio actual.
+ Tanto el nombre como la cantidad de líneas y su contenido es generado aleatoria
+mente (respetando el formato mencionado y con valores racionales).
+\layout Subsection
+
+Parámetros
+\layout Standard
+
+El comando toma 3 parámetros 
+\series bold 
+opcionales
+\series default 
+:
+\layout LyX-Code
+
+./callgen [cant_archivos [min_lineas [max_lineas]]]
+\layout Standard
+
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="4" columns="3">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Parámetro
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Descripción
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+
+\series bold 
+Default
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+cant_archivos
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Cantidad de archivos a generar
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+10
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+min_lineas
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Mínima cantidad de lineas en un archivo
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1000
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+max_linaes
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Máxima cantidad de lineas en un archivo
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+5000
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\layout Subsection
+
+Opciones
+\layout Standard
+
+Pueden cambiarse los valores por defecto editando el código fuente del comando,
+ en la sección de configuración que se encuentra al comienzo del mismo.
+ También puede cambiarse el mínimo y máximo año (por defecto 1999 y 2004)
+ y el mínimo y máximo código de central (por defecto 0000 y 9999).
+\layout Subsection
+
+Ejemplos de invocación
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen
+\layout Paragraph
+
+
+\series medium 
+Se escriben por entrada estándar los códigos de origen/destino, se presiona
+\family typewriter 
+\series default 
+Ctrl-D
+\family default 
+\series medium 
+ para cerrar el descriptor de archivo de la entrada estándar y se generan
+ 10 archivos con entre 1000 y 5000 líneas cada uno.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 2 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 2 archivos con entre 1000 y 5000 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 5 10 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 5 archivos con entre 10 y 5000 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsubsection
+
+
+\family typewriter 
+./callgen 50 10 50 < oridesti.txt
+\layout Paragraph
+
+
+\series medium 
+Genera 50 archivos con entre 10 y 50 líneas cada uno tomando los códigos
+ de origen/destino del archivo 
+\family typewriter 
+origesti.txt
+\family default 
+.
+\layout Subsection
+
+Código Fuente
+\layout LyX-Code
+
+#!/usr/bin/perl -w
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Generador aleatorio de archivos de llamadas
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Leandro Lucarella - dom oct 17 18:37:05 ART 2004
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Bajo licencia GPL.
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Uso:
+\layout LyX-Code
+
+#      ./callgen [cant_archivos [min_lineas [max_lineas]]]
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# cant_archivos Cantidad de archivos a generar.
+\layout LyX-Code
+
+# min_lines     Mínima cantidad de líneas que puede tener un archivo.
+\layout LyX-Code
+
+# max_lines     Máxima cantidad de líneas que puede tener un archivo.
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Por la entrada estándar debe recibir los códigos de países para
+\layout LyX-Code
+
+# origen y/o destino.
+ Toma los dos primeros caracteres por línea como
+\layout LyX-Code
+
+# un código, ignorando el resto, de manera que se puede hacer:
+\layout LyX-Code
+
+#       cat oridesti.txt | ./gencall
+\layout LyX-Code
+
+# Configuración
+\layout LyX-Code
+
+$CANT_ARCHS = 10;
+\layout LyX-Code
+
+$MIN_LINEAS = 1000;
+\layout LyX-Code
+
+$MAX_LINEAS = 5000;
+\layout LyX-Code
+
+$MIN_ANIO   = "1999";
+\layout LyX-Code
+
+$MAX_ANIO   = "2004";
+\layout LyX-Code
+
+$MIN_COD    = "0000";
+\layout LyX-Code
+
+$MAX_COD    = "9999";
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Variables globales
+\layout LyX-Code
+
+our @codes; # Códigos de origen/destino
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Funciones
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ load_codes() - Obtiene códigos de origen/destino de la entrada
+\layout LyX-Code
+
+#                   estándar
+\layout LyX-Code
+
+# Uso: load_codes()
+\layout LyX-Code
+
+sub load_codes()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        push(@codes, substr($_, 0, 2)) while (<STDIN>);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ get_rnd_code() - Obtiene un códigos de origen/destino al azar
+\layout LyX-Code
+
+# Uso: get_rnd_code()
+\layout LyX-Code
+
+sub get_rnd_code()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my $cant = @codes;
+\layout LyX-Code
+
+        return $codes[rnd($cant-1)];
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ rnd() - Genera números aleatorios
+\layout LyX-Code
+
+# Uso: rnd(MAX)      - genera número de 0 a MAX (inclusive)
+\layout LyX-Code
+
+#      rnd(MIN, MAX) - genera número de MIN a MAX (inclusive)
+\layout LyX-Code
+
+#
+\layout LyX-Code
+
+# Nota: respeta el tamaño del campo más chico, es decir, si se usa
+\layout LyX-Code
+
+#       rnd 01 250, el número siempre tendrá al menos 2 dígitos
+\layout LyX-Code
+
+#       rellenados con ceros, como 04, 28, 123, 08, etc
+\layout LyX-Code
+
+sub rnd($;$)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my ($ini, $fin) = @_;
+\layout LyX-Code
+
+        if (!$fin)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $fin = $ini;
+\layout LyX-Code
+
+                $ini = 0;
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        return sprintf('%0'.length($ini).'d', $ini + rand()
+\layout LyX-Code
+
+          * ($fin - $ini + 1));
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Tipos de campos
+\layout LyX-Code
+
+sub aaaa() { return rnd($MIN_ANIO, $MAX_ANIO); } # año
+\layout LyX-Code
+
+sub mm()   { return rnd("01", 12); }             # mes
+\layout LyX-Code
+
+sub dd()   { return rnd("01", 28); }             # día
+\layout LyX-Code
+
+sub hh()   { return rnd("00", 23); }             # hora
+\layout LyX-Code
+
+sub MM()   { return rnd("00", 59); }             # minutos
+\layout LyX-Code
+
+# código de central telefónica
+\layout LyX-Code
+
+sub DDDD() { return rnd($MIN_COD, $MAX_COD); }
+\layout LyX-Code
+
+# caracter aleatorio
+\layout LyX-Code
+
+sub char() { return chr(rnd(65, 90)); }   
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ line() - Genera una línea del archivo
+\layout LyX-Code
+
+sub line()
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my $f_linea   = rnd(100000, 99999999);
+\layout LyX-Code
+
+        my $f_minutos = rnd(1, 150);
+\layout LyX-Code
+
+        my $f_fecha   = aaaa().mm().dd();
+\layout LyX-Code
+
+        my $f_hora    = dd().hh().MM();
+\layout LyX-Code
+
+        my ($f_tipo, $f_orig, $f_dest) = ('', '', '');
+\layout LyX-Code
+
+        if (rnd(1) == 1)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $f_tipo = 'E';
+\layout LyX-Code
+
+                $f_orig = get_rnd_code();
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        else
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                $f_tipo = 'S';
+\layout LyX-Code
+
+                $f_dest = get_rnd_code();
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+        my $f_prest = char().char().char().char().char().
+\layout LyX-Code
+
+                      char().char().char().char();
+\layout LyX-Code
+
+        return "$f_linea;$f_minutos;$f_fecha;$f_hora;".
+\layout LyX-Code
+
+               "$f_tipo;$f_dest;$f_orig;$f_prest";
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ gen() - Genera un archivo con entre MIN y MAX llamadas
+\layout LyX-Code
+
+# Uso: gen(MIN, MAX)
+\layout LyX-Code
+
+sub gen($$)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        my ($ini, $fin) = @_;
+\layout LyX-Code
+
+        my $file = aaaa().mm().dd().hh().MM().'.'.DDDD();
+\layout LyX-Code
+
+        # Mientras exista uno, buscamos un nuevo nombre.
+\layout LyX-Code
+
+        $file = aaaa().mm().dd().hh().MM().'.'.DDDD()
+\layout LyX-Code
+
+          while (-e $file);
+\layout LyX-Code
+
+        open(FH, ">$file")
+\layout LyX-Code
+
+          or die("No puedo abrir el archivo $file!
+\backslash 
+n");
+\layout LyX-Code
+
+        for (my $i = rnd($ini, $fin); $i > 0; --$i)
+\layout LyX-Code
+
+        {
+\layout LyX-Code
+
+                print FH line()."
+\backslash 
+n";
+\layout LyX-Code
+
+        }
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+#{{{ Programa
+\layout LyX-Code
+
+srand;
+\layout LyX-Code
+
+my $cant = $ARGV[0] ? $ARGV[0] : $CANT_ARCHS;
+\layout LyX-Code
+
+load_codes();
+\layout LyX-Code
+
+for (my $i = 0; $i < $cant; ++$i)
+\layout LyX-Code
+
+{
+\layout LyX-Code
+
+        gen($ARGV[1] ? $ARGV[1] : $MIN_LINEAS,
+\layout LyX-Code
+
+            $ARGV[2] ? $ARGV[2] : $MAX_LINEAS);
+\layout LyX-Code
+
+}
+\layout LyX-Code
+
+#}}}
+\layout LyX-Code
+
+\layout LyX-Code
+
+# vim: set fdm=marker ts=4 sw=4 :
+\layout Chapter
+
+Archivos
+\layout Section
+
+Archivos del Enunciado
+\layout Subsection
+
+
+\family typewriter 
+<comando>.log
+\layout Standard
+
+Los archivos de log generados por los distintos comandos, presentan todos
+ la misma estructura de registro que se detalla a continuación: 
+\family typewriter 
+YYYYMMDD-hhmm $usuario $comando: ¨$Mensaje¨
+\layout Subsection
+
+
+\family typewriter 
+oridesti.txt
+\layout Standard
+
+En este archivo se tienen los origenes y destinos en base a los cuales hemos
+ generados los archivos de llamada y los umbrales.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de oridesti.txt
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="2" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Código
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Descripción
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\end_inset 
+
+
+\layout Subsection
+
+
+\family typewriter 
+umbrales.param
+\layout Standard
+
+Este archivo posee los umbrales de llamadas de los cuales se valdra el antifraud
+e.pl para emitir o no alarmas durante el proceso de los archivos de llamadas.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de umbrales.param
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" width="0">
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Id del registro
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, número secuencial >= 1
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Número de línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Origen/Destino
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, valores posibles segun oridesti.txt
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tipo de llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 caracter, E = Entrante, S = Salida
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Estado
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 caracter, A = Activo, I = Inactivo
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Usuario
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres = login del user que graba el reg
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Fecha
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+8 caracteres, formato aaaammdd
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Hora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6 caracteres, formato hhmmss, hora actual
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\end_inset 
+
+
+\layout Subsection
+
+
+\family typewriter 
+<archivo de llamada>
+\layout Standard
+
+Estos archivos son los que el antifraude procesará en busca de matchs contra
+ los umbrales.
+\layout Standard
+
+
+\begin_inset Float table
+placement H
+wide false
+collapsed true
+
+\layout Caption
+
+
+\series bold 
+Estructura de un archivo de llamadas
+\layout Standard
+\align center 
+
+\begin_inset  Tabular
+<lyxtabular version="3" rows="8" columns="2">
+<features>
+<column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
+<column alignment="center" valignment="top" rightline="true" width="0">
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Número de línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Cantidad de Minutos
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, Numérico
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Fecha de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+8 caracteres, formato aaaammdd
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Hora de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+6 caracteres, formato hhmmss
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Tipo de Llamada
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+1 carácter, E = Entrante, S = Salida
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Destino
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, solo informado en llamadas salientes
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Origen
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+2 caracteres, solo informado en llamadas entrantes
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Prestadora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
+
+\end_inset 
+
+
+\end_inset 
+
+
+\layout Subsection
+
+
+\family typewriter 
+alarmas.txt
 \layout Standard
 
-El comando toma 3 parámetros 
-\series bold 
-opcionales
-\series default 
-:
-\layout LyX-Code
-
-./callgen [cant_archivos [min_lineas [max_lineas]]]
-\layout LyX-Code
+En este archivo el antifraude irá dejando registro de las alarmas emitidas
+ en base a registros que han tenido un match contra los umbrales.
+\layout Standard
 
 
 \begin_inset Float table
+placement H
 wide false
-collapsed false
+collapsed true
 
 \layout Caption
 
 
 \series bold 
-Parámetros del comando CALLGEN
+Estructura de alarmas.txt
 \layout Standard
 \align center 
 
 \begin_inset  Tabular
-<lyxtabular version="3" rows="4" columns="3">
+<lyxtabular version="3" rows="10" columns="2">
 <features>
 <column alignment="center" valignment="top" leftline="true" width="0">
-<column alignment="center" valignment="top" leftline="true" width="0">
 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
 <row topline="true" bottomline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
@@ -402,19 +4319,25 @@ Par
 
 \layout Standard
 
+Prestadora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
 
-\series bold 
-Parámetro
+N caracteres, campo 'Prestadora', archivo de llamadas
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-
-\series bold 
-Descripción
+Central Telefónica
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -422,9 +4345,7 @@ Descripci
 
 \layout Standard
 
-
-\series bold 
-Default
+4 caracteres, obtenido a partir del archivo de llamadas
 \end_inset 
 </cell>
 </row>
@@ -434,15 +4355,25 @@ Default
 
 \layout Standard
 
-cant_archivos
+Número de Línea
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+N caracteres, campo 'Numero de Linea' , archivo de llamadas
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-Cantidad de archivos a generar
+Cantidad de minutos
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -450,7 +4381,7 @@ Cantidad de archivos a generar
 
 \layout Standard
 
-10
+N caracteres, campo 'Cant de Minutos', archivo de llamadas
 \end_inset 
 </cell>
 </row>
@@ -460,41 +4391,43 @@ Cantidad de archivos a generar
 
 \layout Standard
 
-min_lineas
+Regla Aplicada
 \end_inset 
 </cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-Mínima cantidad de lineas en un archivo
+N caracteres, campo 'Id de registro', umbrales.param
 \end_inset 
 </cell>
-<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-1000
+Fecha de llamada
 \end_inset 
 </cell>
-</row>
-<row topline="true" bottomline="true">
-<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-max_lines
+8 caracteres, campo 'Fecha de llamada', archivo de llamadas
 \end_inset 
 </cell>
+</row>
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
 \layout Standard
 
-Máxima cantidad de lineas en un archivo
+Hora de llamada
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
 
 \layout Standard
 
-5000
+6 caracteres, campo 'Hora de llamada', archivo de llamadas
 \end_inset 
 </cell>
 </row>
-</lyxtabular>
-
-\end_inset 
-
-
-\end_inset 
-
-
-\layout LyX-Code
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
 \layout Standard
 
+Usuario
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
-\series bold 
-NOTA:
-\series default 
- Pueden cambiarse los valores por defecto editando el código fuente del
- comando, en la sección de configuración que se encuentra al comienzo del
- mismo.
- También puede cambiarse el mínimo y máximo año (por defecto 1999 y 2004)
- y el mínimo y máximo código de central (por defecto 0000 y 9999).
-\layout Subsubsection
-
-Ejemplos de invocación
-\layout Paragraph
-
-./callgen
-\layout Paragraph
-
-
-\series medium 
-Se escriben por entrada estándar los códigos de origen/destino, se presiona
- Ctrl-D para cerrar el descriptor de archivo de la entrada estándar y se
- generan 10 archivos con entre 1000 y 5000 líneas cada uno.
-\layout Paragraph
-
-./callgen 2 < oridesti.txt
-\layout Paragraph
-
-
-\series medium 
-Genera 2 archivos con entre 1000 y 5000 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Paragraph
-
-./callgen 5 10 < oridesti.txt
-\layout Paragraph
-
-
-\series medium 
-Genera 5 archivos con entre 10 y 5000 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Paragraph
-
-./callgen 50 10 50 < oridesti.txt
-\layout Paragraph
-
-
-\series medium 
-Genera 50 archivos con entre 10 y 50 líneas cada uno tomando los códigos
- de origen/destino del archivo origesti.txt.
-\layout Subsubsection
-
-Código Fuente
 \layout Standard
 
-Copy Paste cuando este cerrado.
-\layout Subsection
+N caracteres, siempre login del usuario que graba el reg
+\end_inset 
+</cell>
+</row>
+<row topline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
-util.sh
 \layout Standard
 
+Fecha
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
-\series bold 
-Tipo de comando:
-\series default 
- Auxiliar, escrito en bash scripting
-\layout Subsubsection
-
-Archivos de Input
 \layout Standard
 
-No corresponde
-\layout Subsubsection
+8 caracteres, formato aaaammdd, fecha actual
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
 
-Archivos de Output
 \layout Standard
 
-No corresponde
-\layout Subsubsection
-
-Ejemplos de invocación
-\layout Standard
+Hora
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
 
-No corresponde.
- El archivo es una colección de funciones comunes a los comandos.
 \layout Standard
 
-El archivo contiene las siguientes funciones de uso genérico:
-\layout Enumerate
-
-leer - Permite leer un valor desde el teclado, presentando una opción por
- defecto seleccionada si el usuario ingresa una entrada nula.
-\layout Enumerate
-
-preguntar - Realiza una pregunta al usuario dando un set de opciones válidas
- y solo aceptando una respuesta del set de preguntas.
-\layout Enumerate
-
-validar_solo_numeros - Verifica que la clave pasada contenga solo dígitos.
-\layout Enumerate
-
-lock - Genera un archivo de lock con el PID del programa
-\layout Enumerate
-
-unlock - Eliminar el archivo de lock de un programa
-\layout Enumerate
-
-is_lock - Consulta si un programa está lockeado
-\layout Enumerate
-
-lock_pid - Retorna el PID de un programa lockeado
-\layout Enumerate
-
-validar_rango - Valida si un valor está en un rango de valores
-\layout Enumerate
-
-die - Emite un mensaje de error y retorna al proceso padre un código de
- error
-\layout Enumerate
+6 caracteres formato hhmmss, hora actual
+\end_inset 
+</cell>
+</row>
+</lyxtabular>
 
-perr - Imprime un mensaje por la salida de error estandar
-\layout Enumerate
+\end_inset 
 
-put_log - Agrega una entrada a un archivo de log
-\layout Enumerate
 
-clean_log - Verifica el tamaño del archivo de log y lo trunca de ser necesario
-\layout Subsubsection
+\end_inset 
 
-Código Fuente
-\layout Standard
 
-Copy Paste cuando este cerrado.
 \layout Section
 
-Archivos
-\layout Subsection
-
-Archivos del Enunciado
-\layout Standard
-
-[ Por cada uno se debe poner nombre y detallar su estructura interna ]
-\layout Subsection
-
 Archivos Auxiliares
-\layout Subsubsection
-
-umbrales.id
-\layout Standard
+\layout Subsection
 
-Este archivo contiene el último ID utilizado para los umbrales, a fin de
- no tener que recalcularlo cada vez que se necesita crear un nuevo umbral.
-\layout Subsubsection
 
+\family typewriter 
 afimonio.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/afimonio.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/afimonio.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 afimonio
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
-\layout Subsubsection
+\layout Subsection
 
+
+\family typewriter 
 antifraude.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/antifraude.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/antifraude.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 antifraude.pl
 \family default 
  y la ruta, nombre, y tamaño máximo del archivo de log.
  
-\layout Subsubsection
+\layout Subsection
+
 
+\family typewriter 
 aficonf.conf
 \layout Standard
 
-El archivo de configuración $~/.antifraude/conf/aficonf.conf almacena las
- rutas a los directorios necesarios para la ejecución del script 
+El archivo de configuración 
+\family typewriter 
+~/.antifraude/conf/aficonf.conf
+\family default 
+ almacena las rutas a los directorios necesarios para la ejecución del script
 \family typewriter 
 aficonf
 \family default 
@@ -710,10 +4562,19 @@ aficonf
 
 Estos archivos fueron creados para que los diferentes scripts tengan un
  lugar común donde buscar esa información para salvar el problema comentado
- en el punto 1.2.
+ en el punto 
+\begin_inset LatexCommand \vref{sec:Problemas-relevantes}
+
+\end_inset 
+
+.
 \layout Subsection
 
-Set de Prueba (testcalls.tar.gz)
+Set de Prueba (
+\family typewriter 
+testcalls.tar.gz
+\family default 
+)
 \layout Standard
 
 Para probar el comportamiento del sistema, se preparo un set de prueba distribui
@@ -721,20 +4582,31 @@ do en el archivo
 \family typewriter 
 testcalls.tar.gz
 \family default 
-, situado en el directorio /INST, del paquete de instalación.
+, situado en el directorio 
+\family typewriter 
+/inst
+\family default 
+, del paquete de instalación.
  El set de prueba se copia automáticamente en el momento en que se instale
  el componente 
+\family typewriter 
 \series bold 
-ANTIFRAUDE
+antifraude
+\family default 
 \series default 
 , dejando el escenario listo para procesarlos en el momento en que sea arrancado
  el 
+\family typewriter 
 \series bold 
-AFIMONIO 
+afimonio
+\family default 
 \series default 
 o bien ejecutando el 
+\family typewriter 
 \series bold 
-ANTIFRAUDE
+antifraude
+\family default 
 \series default 
  en forma manual.
 \layout Standard
@@ -747,21 +4619,35 @@ Este set de prueba consta de
 \layout Itemize
 
 14 archivos de llamadas generados con el 
+\family typewriter 
 \series bold 
-CALLGEN
+callgen
+\family default 
 \series default 
 , con entre 1000 y 5000 registros cada uno, y fecha en el rango año 1999
- 2004.
a 2004.
 \layout Itemize
 
-1 archivo de llamadas con registros validos y otros no validos.
+1 archivo de llamadas con registros válidos y otros no válidos.
 \layout Itemize
 
 1 archivo con nombre válido según el formato YYYYMMDDhhmm.nnnn, pero con
- texto dentro suyo, el cual es rechazado por Antifraude.
+ contenido inválido, el cual es rechazado por 
+\family typewriter 
+\series bold 
+antifraude
+\family default 
+\series default 
+.
 \layout Itemize
 
-1 archivo con nombre no válido rechazado en instancia previa por el Afimonio.
+1 archivo con nombre no válido rechazado en instancia previa por 
+\family typewriter 
+\series bold 
+afimonio
+\family default 
+\series default 
+.
 \layout Standard
 
 Se describen en la siguiente tabla, los archivos y registros que disparan
@@ -771,8 +4657,9 @@ Se describen en la siguiente tabla, los archivos y registros que disparan
 
 
 \begin_inset Float table
+placement H
 wide false
-collapsed false
+collapsed true
 
 \layout Caption
 
@@ -806,7 +4693,8 @@ Archivo
 
 
 \series bold 
-Linea Nro
+Nro.
+ Línea
 \end_inset 
 </cell>
 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
@@ -816,7 +4704,7 @@ Linea Nro
 
 
 \series bold 
-Matched Umbral
+Umbral
 \end_inset 
 </cell>
 </row>
@@ -1426,85 +5314,116 @@ Close match umbral 22, difiere tipo de llamada
 \end_inset 
 
 
-\layout Paragraph
+\layout Subsubsection
 
-Archivo 199908220733.4515
+Archivo 
+\family typewriter 
+199908220733.4515
 \layout Paragraph
 
 
 \series medium 
-Posee registros no validos detallados a continuación.
- Los registros se contabilizan de 0 a N (Linea 1 = Reg 0)
-\layout Itemize
+Posee registros no válidos detallados a continuación.
+ Los registros se contabilizan de 0 a N (Línea 1 = Reg 0)
+\layout Description
 
+Registro\SpecialChar ~
 
 \series bold 
-Registro 3
+3
 \series default 
- -> Posee un 9no campo 'Bogus'
-\layout Itemize
+ Posee un 9no campo 
+\emph on 
+bogus
+\layout Description
 
+Registro\SpecialChar ~
 
 \series bold 
-Registro 27
+27
 \series default 
- -> Posee un 9no campo 'Bogus'
-\layout Itemize
+ Posee un 9no campo 
+\emph on 
+bogus
+\layout Description
 
+Registro\SpecialChar ~
 
 \series bold 
-Registro 31
+31
 \series default 
- -> Posee un tipo de llamada 'W' no valida
-\layout Itemize
+ Posee un tipo de llamada 
+\family typewriter 
+W
+\family default 
+ no valida
+\layout Description
 
+Registro\SpecialChar ~
 
 \series bold 
-Registro 41
+41
 \series default 
- -> El numero de linea (campo1) no es numerico, es un string 'ABCD'
-\layout Itemize
+ El número de línea (campo1) no es numérico, es un string 
+\family typewriter 
+'ABCD'
+\layout Description
 
+Registro\SpecialChar ~
 
 \series bold 
-Registro 52
+52
 \series default 
-> Tiene insuficiente cantidad de campos (siete)
Tiene cantidad de campos insuficiente (siete)
 \layout Standard
 
-Estos registros emitirán errores plasmados en el antifraude.log.
- Para verificar esto, realizar un search en el logfile, sobre el nombre
- del archivo, y ubicarse en el sector donde se indica el comienzo del procesamie
-nto del mismo con ¨
+Estos registros emitirán errores plasmados en el 
+\family typewriter 
+antifraude.log
+\family default 
+.
+ Para verificar esto, realizar una búsqueda en el log, sobre el nombre del
+ archivo, y ubicarse en el sector donde se indica el comienzo del procesamiento
+ del mismo con ¨
 \family typewriter 
 Inicio proceso de: 199908220733.4515
 \family default 
 ¨.
-\layout Paragraph
+\layout Subsubsection
 
-Archivo 200412010000.6666
+Archivo 
+\family typewriter 
+200412010000.6666
 \layout Paragraph
 
 
 \series medium 
 Es un archivo de texto el cual pasa el control de Afimonio, pero luego sus
  lineas son descartadas por antifraude y dicho error emitido en el antifraude.log
-\layout Paragraph
+\layout Subsubsection
 
-Archivo 200223.1234
+Archivo 
+\family typewriter 
+200223.1234
 \layout Paragraph
 
 
 \series medium 
 El nombre del archivo no es conforme al formato de nombre estipulado en
- el TP y el mismo es rechazado de antemano por Afimonio.
-\layout Section
+ el TP y el mismo es rechazado de antemano por 
+\family typewriter 
+\series default 
+afimonio
+\family default 
+\series medium 
+.
+\layout Chapter
 
 Apéndice A
-\layout Standard
+\layout Comment
 
-(Esto deberia ser una hoja aparte que solo diga 1.6 Apéndice A) y las hojas
+Esto deberia ser una hoja aparte que solo diga 1.6 Apéndice A) y las hojas
  posteriores son las páginas 3 en adelante del PDF oficial de la catedra,
  sacando la parte de archivos.
- 3-15 más precisamente es lo que iria).
+ 3-15 más precisamente es lo que iria.
 \the_end