Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #include <stdio.h> // pour les msg d'erreur uniquement
- #include <stdnoreturn.h> // C norme 2011
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <errno.h>
- #include <ctype.h>
- #define CODE_ERREUR 255
- #define BUFFER_SIZE 2048
- int dflag = 0;
- int vflag = 0;
- /******************************************************************************
- * Gestion des erreurs
- */
- char *prog; // nom du programme pour les erreurs
- noreturn void raler (int syserr, const char *fmt, ...) {
- va_list ap;
- va_start (ap, fmt);
- fprintf (stderr, "%s: ", prog);
- vfprintf (stderr, fmt, ap);
- fprintf (stderr, "\n");
- va_end (ap);
- if (syserr)
- perror ("");
- exit (CODE_ERREUR);
- }
- noreturn void usage (void) {
- fprintf (stderr, "usage: %s [-d|-v] [fichier-spec]\n", prog);
- exit (1);
- }
- /******************************************************************************
- * Transformation de la spécification en structure d'arbre
- * => utiliser la fonction analyser_spec()
- */
- struct sommet {
- int val; // étiquette du sommet
- struct sommet *frere_suivant; // liste des frères
- struct sommet *premier_fils; // premier des fils
- /*
- * Ce dernier champ (dernier_fils) n'est utilisé que pendant la
- * construction de l'arbre, pour insérer en queue et ainsi
- * respecter l'ordre des processus dans la spécification.
- */
- struct sommet *dernier_fils; // pour insertion en queue
- };
- /*
- * Fonction interne pour l'analyse de la spécification : analyse une
- * ligne de la spécification (la ligne pointée par *spec), et
- * retourne la profondeur, la valeur, et la position suivante (via
- * *spec) et un code pour dire si on a rencontré une erreur, une fin
- * de spéc ou si tout baigne.
- */
- enum ret_al { AL_ERR, AL_FIN, AL_OK }; // retour de analyser_ligne
- enum ret_al analyser_ligne (char **spec, int *prof, int *val) {
- *prof = *val = 0; // mettre les compteurs à 0
- if (**spec == '\0') // spec terminée
- return AL_FIN;
- /*
- * Compter les espaces pour avoir la profondeur
- */
- while (**spec == ' ') {
- (*spec)++;
- (*prof)++;
- }
- /*
- * Récupérer la valeur
- */
- char *debut = *spec; // vérifier au moins un chiffre
- while (isdigit (**spec)) {
- *val = *val * 10 + (**spec - '0');
- (*spec)++;
- }
- if (debut == *spec) // on n'a pas avancé => pb
- return AL_ERR;
- /*
- * Vérifier qu'on est bien à la fin d'une ligne
- */
- if (**spec != '\n')
- return AL_ERR;
- (*spec)++; // passer au sommet suivant
- return AL_OK;
- }
- struct sommet *creer_sommet (int val) {
- struct sommet *s;
- s = malloc (sizeof *s);
- if (s == NULL)
- raler(1, "cannot malloc %d bytes", sizeof *s);
- s->frere_suivant = NULL;
- s->premier_fils = NULL;
- s->dernier_fils = NULL;
- s->val = val;
- return s;
- }
- struct sommet *analyser_spec_profondeur(int *numl, char **spec, int prof) {
- char *nspec;
- int nprof, val;
- struct sommet *s;
- enum ret_al r;
- /*
- * Analyser la racine du sous-arbre
- */
- nspec = *spec;
- r = analyser_ligne(&nspec, &nprof, &val);
- switch (r) {
- case AL_ERR :
- raler (0, "cannot parse spec at line %d", *numl);
- case AL_FIN :
- return NULL;
- case AL_OK : // on continue en séquence
- break;
- default : // programmation défensive
- raler (0, "internal error at line %d", *numl);
- }
- if (nprof != prof)
- raler (0, "unexpected depth (%d) at line %d", nprof, *numl);
- s = creer_sommet (val);
- *spec = nspec;
- (*numl)++;
- /*
- * Chercher les fils directs de la racine
- */
- while ((r= analyser_ligne(&nspec, &nprof, &val)) == AL_OK && nprof > prof) {
- struct sommet *f; // sous-arbre fils trouvé
- nspec = *spec;
- f = analyser_spec_profondeur (numl, &nspec, prof + 1);
- // Est-ce le premier fils ou bien y-a-t'il déjà au moins un ?
- if (s->dernier_fils == NULL) {
- s->premier_fils = s->dernier_fils = f;
- } else {
- s->dernier_fils->frere_suivant = f;
- s->dernier_fils = f;
- }
- *spec = nspec;
- }
- if (r == AL_ERR)
- raler(0, "cannot parse spec at line %d", *numl);
- return s;
- }
- struct sommet *analyser_spec (char *spec)
- {
- struct sommet *s; // arbre obtenu
- int numl; // numéro de ligne pour msg err
- numl = 1;
- s = analyser_spec_profondeur (&numl, &spec, 0);
- if (*spec != '\0') // est-on bien à la fin ?
- raler (0, "invalid spec at line %d", numl);
- return s;
- }
- void readfile(int fd, char* buff) {
- int nb_car;
- int count = 0;
- printf("yo %d \n", getpid());
- while ((nb_car = read(fd, &buff[count], 2048)) != 0 && ) {
- if (nb_car == -1)
- raler (1, "cannot read file");
- count += nb_car;
- if (realloc(buff, sizeof(buff) + 2048) == NULL)
- raler (1, "cannot realloc");
- }
- }
- int cfork (struct sommet* s) {
- pid_t f;
- unsigned int count = 0;
- int w, status, exits = 0;
- struct sommet* current;
- unsigned int i;
- if (s == NULL)
- return 255;
- current = s->premier_fils;
- while (current != NULL) {
- f = fork();
- switch(f) {
- case -1: {
- fprintf(stderr, "buggggggg");
- exit(255);
- break;
- }
- case 0: {
- exit(cfork(current));
- break;
- }
- default: {
- if (vflag)
- printf("pid %d -> %d\n", getpid(), f);
- break;
- }
- }
- current = current->frere_suivant;
- count++;
- }
- if (vflag)
- printf("pid %d : attente %d ms\n", getpid(), s->val);
- usleep(1000 * s->val);
- for (i = 0; i < count; i++) {
- if (wait(&status) == -1)
- raler(0, "wait fail");
- if (WIFEXITED(status) && (w = WEXITSTATUS(status)) < 255) {
- exits += 1 + w;
- } else {
- exit(255);
- }
- }
- if (vflag)
- printf("pid %d <- %d processus\n", getpid(), exits);
- free(s);
- return exits;
- }
- int main(int argc, char** argv) {
- int fd;
- char* buff;
- char c;
- struct sommet* debut;
- while ((c = getopt (argc, argv, "dv")) != -1) {
- switch (c) {
- case 'd':
- dflag = 1;
- break;
- case 'v':
- vflag = 1;
- break;
- default:
- usage();
- }
- }
- buff = malloc(2048);
- if (argc-optind>1 || optind>3){
- usage();
- } else if (argc==optind){
- fd = 0;
- } else {
- fd = open(argv[optind], O_RDONLY);
- }
- if (fd == -1)
- raler (1, "cannot open");
- readfile(fd, buff);
- if (close (fd) == -1)
- raler (1, "cannot close %s", "plop");
- if (dflag)
- printf("%s", buff);
- debut = analyser_spec(buff);
- free(buff);
- exit(cfork(debut) + 1);
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement