--- rpl/src/rpl.c 2011/09/14 14:34:28 1.83 +++ rpl/src/rpl.c 2012/05/21 17:25:46 1.114 @@ -1,7 +1,7 @@ /* ================================================================================ - RPL/2 (R) version 4.1.3 - Copyright (C) 1989-2011 Dr. BERTRAND Joël + RPL/2 (R) version 4.1.9 + Copyright (C) 1989-2012 Dr. BERTRAND Joël This file is part of RPL/2. @@ -23,12 +23,6 @@ #define MAIN_RPL #include "rpl-conv.h" -#ifdef IPCS_SYSV -#ifndef OS2 - unsigned char *chemin_semaphores_SysV; -#endif -#endif - /* ================================================================================ @@ -37,11 +31,21 @@ */ int -rplinit(int argc, char *argv[], unsigned char ***resultats, char *rpl_home) +rplinit(int argc, char *argv[], char *envp[], + unsigned char ***resultats, char *rpl_home) { # include "copyright-conv.h" # include "licence-conv.h" + char **arg_exec; + +# ifdef HAVE_STACK_OVERFLOW_RECOVERY + char pile_signaux[SIGSTKSZ]; +# endif + +# define RPL_PATH_MAX 1024 + char repertoire_initial[RPL_PATH_MAX]; + file *f_source; int erreur_historique; @@ -105,6 +109,8 @@ rplinit(int argc, char *argv[], unsigned volatile unsigned char traitement_fichier_temporaire; errno = 0; + s_queue_signaux = NULL; + routine_recursive = 0; pid_processus_pere = getpid(); # ifdef DEBUG_MEMOIRE @@ -115,18 +121,11 @@ rplinit(int argc, char *argv[], unsigned setvbuf(stderr, NULL, _IOLBF, 0); # ifndef SEMAPHORES_NOMMES - sem_init(&semaphore_liste_threads, 0, 1); sem_init(&semaphore_gestionnaires_signaux, 0, 0); - sem_init(&semaphore_gestionnaires_signaux_atomique, 0, 1); # else - semaphore_liste_threads = sem_init2(1, sem_liste_threads); - semaphore_gestionnaires_signaux = sem_init2(0, sem_gestionnaires_signaux); - semaphore_gestionnaires_signaux_atomique = sem_init2(1, - sem_gestionnaires_signaux_atomique); - - if ((semaphore_liste_threads == SEM_FAILED) || - (semaphore_gestionnaires_signaux == SEM_FAILED) || - (semaphore_gestionnaires_signaux_atomique == SEM_FAILED)) + semaphore_gestionnaires_signaux = sem_init2(0, getpid(), SEM_SIGNAUX); + + if (semaphore_gestionnaires_signaux == SEM_FAILED) { erreur = d_es_allocation_memoire; @@ -183,14 +182,62 @@ rplinit(int argc, char *argv[], unsigned (*s_etat_processus).langue = 'E'; } + if (getcwd(repertoire_initial, RPL_PATH_MAX) == NULL) + { + if ((langue = getenv("LANG")) != NULL) + { + if (strncmp(langue, "fr", 2) == 0) + { + uprintf("+++Système : Mémoire insuffisante\n"); + } + else + { + uprintf("+++System : Not enough memory\n"); + } + } + else + { + uprintf("+++System : Not enough memory\n"); + } + + return(EXIT_FAILURE); + } + + if ((arg_exec = malloc((argc + 1) * sizeof(char *))) == NULL) + { + if ((langue = getenv("LANG")) != NULL) + { + if (strncmp(langue, "fr", 2) == 0) + { + uprintf("+++Système : Mémoire insuffisante\n"); + } + else + { + uprintf("+++System : Not enough memory\n"); + } + } + else + { + uprintf("+++System : Not enough memory\n"); + } + + return(EXIT_FAILURE); + } + + for(i = 0; i < (unsigned long) argc; i++) + { + arg_exec[i] = argv[i]; + } + + argv[argc] = NULL; + initialisation_contexte_cas(s_etat_processus); (*s_etat_processus).exception = d_ep; (*s_etat_processus).erreur_systeme = d_es; (*s_etat_processus).erreur_execution = d_ex; - (*s_etat_processus).compteur_violation_d_acces = 0; - (*s_etat_processus).tid_courant = pthread_self(); + (*s_etat_processus).requete_redemarrage = d_faux; (*s_etat_processus).rpl_home = rpl_home; pthread_mutexattr_init(&attributs_mutex); @@ -205,22 +252,22 @@ rplinit(int argc, char *argv[], unsigned pthread_mutexattr_destroy(&attributs_mutex); # ifndef SEMAPHORES_NOMMES - sem_init(&((*s_etat_processus).semaphore_fork), 0, 0); + sem_init(&((*s_etat_processus).semaphore_fork), 0, 0); # else - if (((*s_etat_processus).semaphore_fork = sem_init2(0, sem_fork)) == - SEM_FAILED) - { - if ((*s_etat_processus).langue == 'F') - { - uprintf("+++Système : Mémoire insuffisante\n"); - } - else + if (((*s_etat_processus).semaphore_fork = sem_init3(0, getpid(), + pthread_self(), SEM_FORK)) == SEM_FAILED) { - uprintf("+++System : Not enough memory\n"); - } + if ((*s_etat_processus).langue == 'F') + { + uprintf("+++Système : Mémoire insuffisante\n"); + } + else + { + uprintf("+++System : Not enough memory\n"); + } - return(EXIT_FAILURE); - } + return(EXIT_FAILURE); + } # endif pthread_mutexattr_init(&attributs_mutex); @@ -244,13 +291,6 @@ rplinit(int argc, char *argv[], unsigned (*s_etat_processus).chemin_fichiers_temporaires = recherche_chemin_fichiers_temporaires(s_etat_processus); -# ifdef IPCS_SYSV -# ifndef OS2 - chemin_semaphores_SysV = - (*s_etat_processus).chemin_fichiers_temporaires; -# endif -# endif - insertion_thread(s_etat_processus, d_vrai); creation_queue_signaux(s_etat_processus); @@ -305,11 +345,11 @@ rplinit(int argc, char *argv[], unsigned if ((*s_etat_processus).langue == 'F') { - printf("+++Copyright (C) 1989 à 2010, 2011 BERTRAND Joël\n"); + printf("+++Copyright (C) 1989 à 2011, 2012 BERTRAND Joël\n"); } else { - printf("+++Copyright (C) 1989 to 2010, 2011 BERTRAND Joel\n"); + printf("+++Copyright (C) 1989 to 2011, 2012 BERTRAND Joel\n"); } if (getenv("HOME") != NULL) @@ -334,88 +374,79 @@ rplinit(int argc, char *argv[], unsigned home = ""; } - // Initialisation d'une clef - - if (pthread_key_create(&semaphore_fork_processus_courant, NULL) != 0) - { - if ((*s_etat_processus).langue == 'F') - { - printf("+++Système : Mémoire insuffisante\n"); - } - else +# ifdef HAVE_STACK_OVERFLOW_RECOVERY + if (stackoverflow_install_handler(interruption_depassement_pile, + pile_signaux, sizeof(pile_signaux)) != 0) { - printf("+++System : Not enough memory\n"); - } + erreur = d_es_signal; - return(EXIT_FAILURE); - } + if ((*s_etat_processus).langue == 'F') + { + printf("+++Système : Initialisation de la pile alternative " + "impossible\n"); + } + else + { + printf("+++System : Initialization of alternate " + "stack failed\n"); + } -# ifndef SEMAPHORES_NOMMES - if (pthread_setspecific(semaphore_fork_processus_courant, - &((*s_etat_processus).semaphore_fork)) != 0) + return(EXIT_FAILURE); + } # else - if (pthread_setspecific(semaphore_fork_processus_courant, - (*s_etat_processus).semaphore_fork) != 0) -# endif - { if ((*s_etat_processus).langue == 'F') { - printf("+++Système : Mémoire insuffisante\n"); + printf("+++Attention : Le système ne supporte pas de pile " + "alternative\n"); } else { - printf("+++System : Not enough memory\n"); + printf("+++Warning : Operating system does not support alternate " + "stack\n"); } +# endif - return(EXIT_FAILURE); - } - - // Initialisation d'une pile de signal pour récupérer les - // débordement de pile + action.sa_handler = interruption1; + action.sa_flags = 0; -# if !defined(Cygwin) && !defined(OpenBSD) - if (((*s_etat_processus).pile_signal.ss_sp = - malloc((*s_etat_processus).pile_signal.ss_size = - SIGSTKSZ)) == NULL) + if (sigaction(SIGINT, &action, NULL) != 0) { - erreur = d_es_allocation_memoire; + erreur = d_es_signal; if ((*s_etat_processus).langue == 'F') { - printf("+++Système : Mémoire insuffisante\n"); + printf("+++Système : Initialisation des signaux POSIX " + "impossible\n"); } else { - printf("+++System : Not enough memory\n"); + printf("+++System : Initialization of POSIX signals failed\n"); } return(EXIT_FAILURE); } - (*s_etat_processus).pile_signal.ss_flags = 0; + signal_test = SIGTEST; + kill(getpid(), SIGINT); - if (sigaltstack(&((*s_etat_processus).pile_signal), NULL) != 0) + if (signal_test != SIGINT) { erreur = d_es_signal; if ((*s_etat_processus).langue == 'F') { - printf("+++Système : Initialisation de la pile spécifique de signal" - " impossible\n"); + printf("+++Système : Initialisation des signaux POSIX " + "impossible\n"); } else { - printf("+++System : Initialization of signal stack failed\n"); + printf("+++System : Initialization of POSIX signals failed\n"); } return(EXIT_FAILURE); } -# endif - action.sa_handler = interruption1; - action.sa_flags = SA_ONSTACK; - - if (sigaction(SIGINT, &action, NULL) != 0) + if (sigaction(SIGTERM, &action, NULL) != 0) { erreur = d_es_signal; @@ -433,9 +464,9 @@ rplinit(int argc, char *argv[], unsigned } signal_test = SIGTEST; - kill(getpid(), SIGINT); + kill(getpid(), SIGTERM); - if (signal_test != SIGINT) + if (signal_test != SIGTERM) { erreur = d_es_signal; @@ -452,7 +483,7 @@ rplinit(int argc, char *argv[], unsigned return(EXIT_FAILURE); } - if (sigaction(SIGTERM, &action, NULL) != 0) + if (sigaction(SIGALRM, &action, NULL) != 0) { erreur = d_es_signal; @@ -470,9 +501,9 @@ rplinit(int argc, char *argv[], unsigned } signal_test = SIGTEST; - kill(getpid(), SIGTERM); + kill(getpid(), SIGALRM); - if (signal_test != SIGTERM) + if (signal_test != SIGALRM) { erreur = d_es_signal; @@ -490,7 +521,7 @@ rplinit(int argc, char *argv[], unsigned } action.sa_handler = interruption2; - action.sa_flags = SA_NODEFER | SA_ONSTACK; + action.sa_flags = 0; if (sigaction(SIGTSTP, &action, NULL) != 0) { @@ -528,7 +559,7 @@ rplinit(int argc, char *argv[], unsigned } action.sa_handler = interruption5; - action.sa_flags = SA_NODEFER | SA_ONSTACK; + action.sa_flags = 0; if (sigaction(SIGPIPE, &action, NULL) != 0) { @@ -568,9 +599,9 @@ rplinit(int argc, char *argv[], unsigned } action.sa_handler = interruption1; - action.sa_flags = SA_NODEFER | SA_ONSTACK; + action.sa_flags = 0; - if (sigaction(SIGALRM, &action, NULL) != 0) + if (sigaction(SIGUSR1, &action, NULL) != 0) { erreur = d_es_signal; @@ -588,9 +619,9 @@ rplinit(int argc, char *argv[], unsigned } signal_test = SIGTEST; - kill(getpid(), SIGALRM); + kill(getpid(), SIGUSR1); - if (signal_test != SIGALRM) + if (signal_test != SIGUSR1) { erreur = d_es_signal; @@ -655,6 +686,15 @@ rplinit(int argc, char *argv[], unsigned option_t = d_faux; option_v = d_faux; + // Lorsque le programme est appelé depuis un shebang, argv[0] contient + // le chemin du programme et argv[1] tous les arguments. + // argv[2] contient quant à lui le nom du script RPL/2. + // + // Exemple : + // argv[0] : /usr/local/bin/rpl + // argv[1] : -csdp -t 800 + // argv[2] : ./on_exit.rpl + while((--argc) > 0) { if ((*(++argv))[0] == '-') @@ -1450,6 +1490,12 @@ rplinit(int argc, char *argv[], unsigned break; } + case '-': + case ' ': + { + break; + } + default : { if ((*s_etat_processus).langue == 'F') @@ -1494,10 +1540,36 @@ rplinit(int argc, char *argv[], unsigned } } + /* + * Dans le cas où le programme est appelé avec l'option -d, + * on ne récupère par les signaux de violation d'accès. On + * tente simplement la récupération des dépassements de pile. + */ + if (debug == d_faux) { + +# ifdef HAVE_SIGSEGV_RECOVERY + if (sigsegv_install_handler(interruption_violation_access) != 0) + { + erreur = d_es_signal; + + if ((*s_etat_processus).langue == 'F') + { + printf("+++Système : Initialisation de la pile alternative " + "impossible\n"); + } + else + { + printf("+++System : Initialization of alternate " + "stack failed\n"); + } + + return(EXIT_FAILURE); + } +# else action.sa_handler = interruption3; - action.sa_flags = SA_NODEFER | SA_ONSTACK; + action.sa_flags = 0; if (sigaction(SIGSEGV, &action, NULL) != 0) { @@ -1515,6 +1587,28 @@ rplinit(int argc, char *argv[], unsigned return(EXIT_FAILURE); } + signal_test = SIGTEST; + kill(getpid(), SIGSEGV); + + if (signal_test != SIGSEGV) + { + erreur = d_es_signal; + + if ((*s_etat_processus).langue == 'F') + { + printf("+++Système : Initialisation des signaux POSIX " + "impossible\n"); + } + else + { + printf("+++System : Initialization of POSIX signals " + "failed\n"); + } + + return(EXIT_FAILURE); + } +# endif + if (sigaction(SIGBUS, &action, NULL) != 0) { if ((*s_etat_processus).langue == 'F') @@ -1530,12 +1624,34 @@ rplinit(int argc, char *argv[], unsigned return(EXIT_FAILURE); } + + signal_test = SIGTEST; + kill(getpid(), SIGBUS); + + if (signal_test != SIGBUS) + { + erreur = d_es_signal; + + if ((*s_etat_processus).langue == 'F') + { + printf("+++Système : Initialisation des signaux POSIX " + "impossible\n"); + } + else + { + printf("+++System : Initialization of POSIX signals " + "failed\n"); + } + + return(EXIT_FAILURE); + } + } if (option_n == d_vrai) { action.sa_handler = interruption4; - action.sa_flags = SA_ONSTACK; + action.sa_flags = 0; if (sigaction(SIGHUP, &action, NULL) != 0) { @@ -1916,6 +2032,7 @@ rplinit(int argc, char *argv[], unsigned (*s_etat_processus).arbre_instructions = NULL; (*s_etat_processus).tid_processus_pere = pthread_self(); + (*s_etat_processus).tid = pthread_self(); (*s_etat_processus).pid_processus_pere = getpid(); (*s_etat_processus).processus_detache = d_vrai; (*s_etat_processus).var_volatile_processus_pere = -1; @@ -2012,12 +2129,10 @@ rplinit(int argc, char *argv[], unsigned (*((*s_etat_processus).l_base_pile_systeme)) .retour_definition = 'Y'; - (*s_etat_processus).indep = (struct_objet *) malloc( - sizeof(struct_objet)); - (*s_etat_processus).depend = (struct_objet *) malloc( - sizeof(struct_objet)); + (*s_etat_processus).indep = allocation(s_etat_processus, NON); + (*s_etat_processus).depend = allocation(s_etat_processus, NON); (*s_etat_processus).parametres_courbes_de_niveau = - (struct_objet *) malloc(sizeof(struct_objet)); + allocation(s_etat_processus, NON); if (((*s_etat_processus).indep != NULL) && ((*s_etat_processus).depend != NULL) && @@ -2427,6 +2542,11 @@ rplinit(int argc, char *argv[], unsigned home, ds_fichier_historique); using_history(); + + // Pour pouvoir utiliser le keymap avant le premier + // appel à readline(). + rl_initialize(); + erreur_historique = read_history( (*s_etat_processus).nom_fichier_historique); @@ -2679,8 +2799,6 @@ rplinit(int argc, char *argv[], unsigned lancement_daemon(s_etat_processus); } -// A FIXER -// création signaux if (option_p == d_faux) { if (setjmp(contexte_initial) == 0) @@ -2723,8 +2841,6 @@ rplinit(int argc, char *argv[], unsigned } } } -// A FIXER -// destruction signaux } liberation(s_etat_processus, (*s_etat_processus).at_exit); @@ -2738,16 +2854,6 @@ rplinit(int argc, char *argv[], unsigned l_element_courant = (*s_etat_processus).liste_mutexes; while(l_element_courant != NULL) { - pthread_mutex_trylock(&((*((struct_mutex *) - (*(*((struct_liste_chainee *) - l_element_courant)).donnee).objet)).mutex)); - pthread_mutex_unlock(&((*((struct_mutex *) - (*(*((struct_liste_chainee *) - l_element_courant)).donnee).objet)).mutex)); - pthread_mutex_destroy(&((*((struct_mutex *) - (*(*((struct_liste_chainee *) - l_element_courant)).donnee).objet)).mutex)); - liberation(s_etat_processus, (*((struct_liste_chainee *) l_element_courant)).donnee); @@ -2959,7 +3065,7 @@ rplinit(int argc, char *argv[], unsigned .thread).nombre_objets_dans_pipe--; action.sa_handler = SIG_IGN; - action.sa_flags = SA_ONSTACK; + action.sa_flags = 0; if (sigaction(SIGPIPE, &action, ®istre) != 0) @@ -3005,6 +3111,7 @@ rplinit(int argc, char *argv[], unsigned } nanosleep(&attente, NULL); + scrutation_interruptions(s_etat_processus); pthread_mutex_lock(&((*s_etat_processus).mutex)); } @@ -3535,31 +3642,36 @@ rplinit(int argc, char *argv[], unsigned sem_destroy(&((*s_etat_processus).semaphore_fork)); # else sem_post((*s_etat_processus).semaphore_fork); - sem_destroy2((*s_etat_processus).semaphore_fork, sem_fork); + sem_destroy3((*s_etat_processus).semaphore_fork, getpid(), pthread_self(), + SEM_FORK); # endif free((*s_etat_processus).localisation); -# ifndef SEMAPHORES_NOMMES - sem_destroy(&semaphore_liste_threads); -# else - sem_destroy2(semaphore_liste_threads, sem_liste_threads); -# endif + pthread_mutex_destroy(&mutex_liste_threads); + pthread_mutex_destroy(&mutex_gestionnaires_signaux_atomique); + # ifndef SEMAPHORES_NOMMES sem_post(&semaphore_gestionnaires_signaux); sem_destroy(&semaphore_gestionnaires_signaux); - sem_destroy(&semaphore_gestionnaires_signaux_atomique); # else sem_post(semaphore_gestionnaires_signaux); - sem_destroy2(semaphore_gestionnaires_signaux, sem_gestionnaires_signaux); - sem_destroy2(semaphore_gestionnaires_signaux_atomique, - sem_gestionnaires_signaux_atomique); + sem_destroy2(semaphore_gestionnaires_signaux, getpid(), SEM_SIGNAUX); # endif destruction_queue_signaux(s_etat_processus); liberation_contexte_cas(s_etat_processus); free((*s_etat_processus).chemin_fichiers_temporaires); + + if ((*s_etat_processus).requete_redemarrage == d_vrai) + { + chdir(repertoire_initial); + execvp(arg_exec[0], &(arg_exec[0])); + erreur = d_erreur; + } + + free(arg_exec); free(s_etat_processus); # ifdef DEBUG_MEMOIRE @@ -3567,6 +3679,17 @@ rplinit(int argc, char *argv[], unsigned analyse_post_mortem(); # endif +# ifdef HAVE_STACK_OVERFLOW_RECOVERY + stackoverflow_deinstall_handler(); +# endif + +# ifdef HAVE_SIGSEGV_RECOVERY + if (debug == d_faux) + { + sigsegv_deinstall_handler(); + } +# endif + return((erreur == d_absence_erreur) ? EXIT_SUCCESS : EXIT_FAILURE); } @@ -3622,4 +3745,72 @@ informations(struct_processus *s_etat_pr return; } + +logical1 +controle_integrite(struct_processus *s_etat_processus, + unsigned char *executable_candidat, unsigned char *executable) +{ + unsigned char *md5; + unsigned char *sha1; + + if (strcmp(executable, "rplpp") == 0) + { + md5 = rplpp_md5; + sha1 = rplpp_sha1; + } + else if (strcmp(executable, "rplfile") == 0) + { + md5 = rplfile_md5; + sha1 = rplfile_sha1; + } + else if (strcmp(executable, "rpliconv") == 0) + { + md5 = rpliconv_md5; + sha1 = rpliconv_sha1; + } + else if (strcmp(executable, "rplawk") == 0) + { + md5 = rplawk_md5; + sha1 = rplawk_sha1; + } + else if (strcmp(executable, "rplconvert") == 0) + { + md5 = rplconvert_md5; + sha1 = rplconvert_sha1; + } + else + { + return(d_faux); + } + + if (controle(s_etat_processus, executable_candidat, "md5", md5) != d_vrai) + { + return(d_faux); + } + + if (controle(s_etat_processus, executable_candidat, "sha1", sha1) != d_vrai) + { + return(d_faux); + } + + return(d_vrai); +} + + +unsigned char * +date_compilation() +{ + unsigned char *date; + + if ((date = malloc((strlen(d_date_en_rpl) + 1) * sizeof(unsigned char))) + == NULL) + { + return(NULL); + } + + strcpy(date, d_date_en_rpl); + + return(date); +} + // vim: ts=4