Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: allnex en 5 Noviembre 2017, 12:09 pm



Título: Parar todos los forks después de señal
Publicado por: allnex en 5 Noviembre 2017, 12:09 pm
Hola, muy buenas.

Tengo un problema con el manejo de señales. El siguiente programa crea dos procesos hijo y busca secuencialmente una contraseña cifrada. El primer hijo busca desde el principio hasta la mitad, y el segundo hijo desde la mitad hasta el final. El principio y fin lo pasa el usuario a través de argumentos.

El programa funciona bien si se ejecuta, cuando encuentra la contraseña se matan a los hijos y se sale, pero si ejecuto el comando "time ./programa ...." solo finaliza el hijo que ha encontrado la clave, el otro hasta el final no acaba.

No sé que estoy haciendo mal para que funciona normalmente, pero con time no lo haga correctamente.

Muchas gracias.

Código
  1. struct sigaction trataSenial ;
  2.  
  3. void handler(int sig)
  4. {
  5. if (sig == SIGUSR1)
  6. {
  7. printf("[H] [%d] recibe la señal SIGUSR1\n", getpid());
  8. exit(0);
  9. }
  10. }
  11.  
  12. void handler_padre(int sig) {
  13. if (sig == SIGUSR1)
  14. {
  15. printf("[P] [%d] recibe la señal SIGUSR1\n", getpid());
  16. exit(0);
  17. }
  18. }
  19.  
  20. void siguientePassword ( char * pwd )               /* orden lexicografico */
  21. {                                                              /* circular */
  22.    int lenPwd = strlen(pwd) ;
  23. int i = lenPwd-1 ;
  24. while ( i >= 0)
  25.        if (++(pwd[i]) > 'z')
  26. pwd[i--] = 'a' ;
  27.        else
  28. return ;
  29. }
  30.  
  31. int valor ( const char * pwd )     /* valor de la clave (base 'z'-'a' + 1) */
  32. {
  33. int base = 'z' - 'a' + 1 ;
  34. int acum = 0 ;
  35. int lenPwd = strlen(pwd) ;
  36. int i = 0 ;
  37. for ( i = 0 ; i < lenPwd ; i++ )
  38.        acum = base*acum + (pwd[i] - 'a') ;
  39.    return(acum) ;
  40. }
  41.  
  42. int obtenPwd ( int valor, char * pwd )
  43. {
  44. int base = 'z' - 'a' + 1 ;
  45. int resto = valor ;
  46. int lenPwd = strlen(pwd) ;
  47. int i = lenPwd-1 ;
  48.  
  49. while ((i >= 0) && (resto > 0))
  50. {
  51.        pwd[i] = 'a' + (char)(resto % base) ;
  52.    resto = resto / base ;
  53.        i-- ;
  54. }
  55. while ( i >= 0) pwd[i--] = 'a' ;
  56. }
  57.  
  58. int analizarArgumentos ( int argc, char * argv [ ], int * verbose )
  59. {
  60.  
  61. char * pwd_0 ;        /* password inicial (de comienzo de la busqueda) */
  62. char * pwd_1 ;        /* password final   (de fin      de la busqueda) */
  63.    int length_pwd ;                          /* longitud de los passwords */
  64. int i ;
  65.  
  66.    if (argc < 4)
  67.    {
  68.        printf(
  69.    "\n"
  70. " formato: despara2 <palabra_cifrada> <pwd_0> <pwd_1> [-v|-p] \n"
  71. "\n"
  72. ) ;
  73.        return(1) ;
  74.    }
  75.  
  76. pwd_0 = argv[2] ;
  77. pwd_1 = argv[3] ;
  78. length_pwd = strlen(pwd_0) ;
  79. if (strlen(pwd_1) != length_pwd)
  80. {
  81.        printf(
  82.    "\n"
  83. " <pwd_0> y <pwd_1> deben tener la misma longitud \n"
  84. "\n"
  85. ) ;
  86.        return(2) ;
  87. }
  88.  
  89. for ( i = 0 ; i < length_pwd ; i++ )
  90. if (!(isalpha(pwd_0[i]) && islower(pwd_0[i]) &&  
  91.      isalpha(pwd_1[i]) && islower(pwd_1[i])))
  92.    {
  93.    "\n"
  94. " <pwd_0> y <pwd_1> deben contener solo letras minusculas \n"
  95. "\n"
  96. ) ;
  97.        return(3) ;
  98. }
  99.  
  100.    if (strcmp(pwd_0, pwd_1) > 0) {
  101.    "\n"
  102. " <pwd_0> debe ser <= que <pwd_1> en orden lexicográfico \n"
  103. "\n"
  104. ) ;
  105.        return(4) ;
  106. }
  107.  
  108. if (strncmp(argv[1], "aa", 2) != 0)
  109. {
  110.    "\n"
  111. " la clave cifrada \"%s\" debe comenzar con \"aa\" \n"
  112. "\n", argv[1]
  113. ) ;
  114.        return(5) ;
  115.    }
  116.  
  117. if (argc >= 5)
  118. {
  119.    if (strcmp(argv[4], "-v") == 0) *verbose = 1 ;
  120.    else if (strcmp(argv[4], "-p") == 0) *verbose = 2 ;
  121.    else *verbose = 0 ;
  122.    }
  123.    else verbose = 0 ;
  124.  
  125. return(0) ;
  126.  
  127. }
  128.  
  129. #define macro_verbose \
  130.    if (verbose == 1)                                                  \
  131.    {                                                                  \
  132.    printf("\r") ;     \
  133.             printf(" test i = %10d probando con pwd = %s", i-i_0+1, pwd) ; \
  134. }                                                                  \
  135.         else if (verbose == 2)                                             \
  136.    {                                                                  \
  137.    printf("\r") ;     \
  138.             printf(" progreso = %2d %c", (100*(i-i_0+1))/(i_1-i_0+1),'%') ;\
  139. }                                                                  \
  140.  
  141. int buscaEImprimeClave ( char * claveCifrada,
  142.                         char * pwd_0,
  143. char * pwd_1,
  144.                         int  verbose,
  145.                         int  pidOtro )
  146. {
  147.    char * pwd ;
  148. int length_pwd ;
  149. int i_0 = valor(pwd_0) ;
  150. int i_1 = valor(pwd_1) ;
  151. int i, j ;
  152.  
  153. length_pwd = strlen(pwd_0) ;
  154. pwd = malloc(length_pwd+1) ;
  155. strcpy(pwd, pwd_0) ;
  156.  
  157.    printf("\n") ;
  158. for ( i = i_0 ; i <= i_1 ; i++ )
  159. {
  160.        macro_verbose ;      /* macro para mostrar el progreso con -v o -p */
  161.  
  162.        if (strcmp(claveCifrada, crypt(pwd, "aa")) == 0)
  163.        {
  164.            if (verbose > 0) printf("\n\n") ;
  165.            printf ("la password es: %s (iteraciones = %d = %2d %c)\n",
  166.          pwd, i-i_0+1, (100*(i-i_0+1))/(i_1-i_0+1),'%') ;
  167.          free(pwd);  
  168.     kill(-pidOtro, SIGUSR1);
  169.     exit(0);
  170.        }
  171.  
  172.        siguientePassword(pwd) ;
  173.    }
  174.    if (verbose > 0) printf("\n\n") ;
  175. printf(" la clave \"%s\" no es una clave cifrada \n", claveCifrada) ;
  176.    free(pwd)
  177.    return(6) ;                                              
  178. }
  179.  
  180. int main ( int argc, char * argv [ ] )
  181. {
  182.  
  183. char * claveCifrada = argv[1] ;     /* resultado de cifrar el password */
  184. char * pwd_0 = argv[2] ;            /* password inicial de busqueda    */
  185. char * pwd_1 = argv[3] ;            /* password final de busqueda      */
  186.  
  187. int verbose ;  /* 0, 1 o 2 (grado de escritura de mensajes con printf) */
  188.  
  189. int pid, pid_1, pid_2 ;
  190. char pwdMedio [6] ;
  191. int estado ;
  192. int parent = getpid();
  193.  
  194. trataSenial.sa_handler = handler_padre ;
  195. sigaction(SIGUSR1, &trataSenial, NULL) ;
  196.  
  197. int resultado = analizarArgumentos(argc, argv, &verbose) ;
  198.  
  199. if (resultado != 0) return(resultado) ;
  200.  
  201.    strcpy(pwdMedio, pwd_0) ;
  202.  
  203.    obtenPwd((valor(pwd_0)+valor(pwd_1))/2, (char *)&pwdMedio) ;    
  204.  
  205. printf("pwdMedio = \"%s\"\n\n", pwdMedio) ;
  206. printf("[P] [%d] iniciado\n", getpid());
  207.                                                /* ver: setsid, kill(0, _) */
  208.  
  209. pid_1 = fork() ;
  210. if (pid_1 == 0) {
  211. printf("[H1] [%d] iniciado", getpid());
  212. signal(SIGUSR1, handler);
  213.    resultado =
  214.    buscaEImprimeClave(claveCifrada, pwd_0, pwdMedio, 0, parent) ;
  215. return(resultado) ;
  216. }
  217. pid_2 = fork() ;
  218. if (pid_2 == 0) {
  219. printf("[H2] [%d] iniciado\n", getpid());
  220. signal(SIGUSR1, handler);
  221.        siguientePassword(pwdMedio) ;
  222.    resultado =
  223.        buscaEImprimeClave(claveCifrada, pwdMedio, pwd_1, 0, parent) ;
  224. return(resultado) ;
  225.    }
  226.    waitpid(pid_1, &estado, 0) ;
  227.    waitpid(pid_2, &estado, 0) ;
  228.    /*pid = wait((int *)&estado) ;
  229.     pid = wait((int *)&estado) ;*/
  230.  
  231. printf("\n fin del proceso padre\n\n") ;
  232.    return(0) ;
  233. }
  234.