execrom

Exécuteur de roms
git clone git://git.asteride.xyz/execrom.git
Journaux | Fichiers | Références | LISEZ-MOI | LICENCE

execrom.c (3343B)


      1 /*
      2  * Copyright (c) 2025 Loïc Daignault-Pichette <ldp@asteride.xyz>
      3  *
      4  * Ce fichier fait partie d'execrom, partagé sous la licence GPLv3 (seulement).
      5  * Consultez le fichier LICENCE ou le site <https://www.gnu.org/licenses/> pour
      6  * plus de détails.
      7  */
      8 
      9 #include <dirent.h>
     10 #include <errno.h>
     11 #include <limits.h>
     12 #include <stdio.h>
     13 #include <stdlib.h>
     14 #include <string.h>
     15 #include <unistd.h>
     16 
     17 #ifndef NAME_MAX
     18 #define NAME_MAX 255
     19 #endif
     20 
     21 extern char **environ;
     22 
     23 int
     24 main(int argc, char **argv)
     25 {
     26 	size_t taille; /* Taille du nom de la ROM */
     27 	char *chems; /* Pointeur vers le contenu d’EXECROM_CHEM */
     28 	char *chem; /* Variable temporaire vers un chemin */
     29 	char *chemrom; /* Chemin vers la ROM */
     30 	char *interp; /* Nom de l’interpréteur */
     31 	char nomrom[NAME_MAX+1]; /* nom de la ROM */
     32 	char **args; /* Vecteur d’arguments à transmettre à l’interpréteur */
     33 	DIR *dossier;
     34 	struct dirent *dp;
     35 
     36         /* execrom a besoin du nom du programme, car c’est ce qui lui permet
     37            d’identifier la ROM à lancer. */
     38 	if (argc < 1) {
     39 		fprintf(stderr, "execrom: programme lancé sans nom\n");
     40 		return 1;
     41 	}
     42 
     43         /* La variable d’environnement EXECROM_CHEM doit contenir une liste de
     44            chemins où trouver les ROMs. Il n’y a pas de chemin par défaut. */
     45 	if ((chems = getenv("EXECROM_CHEM")) == NULL || chems[0] == '\0') {
     46 		fprintf(stderr, "execrom: EXECROM_CHEM est vide\n");
     47 		return 1;
     48 	}
     49 
     50         /* Ne conserver que le nom du fichier. Important, puisque le programme
     51            peut être lancé à l’aide d’un chemin relatif, comme
     52 	   ../catalogue/rom. */
     53 	for (chem = strtok(argv[0], "/"); chem; chem = strtok(NULL, "/"))
     54 		argv[0] = chem;
     55 
     56         /* La taille du nom de la ROM est fournie en argument à strncmp. */
     57 	taille = strlen(argv[0]);
     58 
     59         /* Chaque dossier contenu dans EXECROM_CHEM est parcouru. La recherche
     60            s’arrête lorsqu’un fichier commence par argv[0], suivi d’un point
     61            (« . ») */
     62 	for (chem = strtok(chems, ":"); chem; chem = strtok(NULL, ":")) {
     63 		/* Tenter d’ouvrir le dossier. */
     64 		if ((dossier = opendir(chem)) == NULL) {
     65 			fprintf(stderr, "execrom: %s: %s\n",
     66 				chem, strerror(errno));
     67 			return 1;
     68 		}
     69 
     70 		while ((dp = readdir(dossier)) != NULL) {
     71 			if (strncmp(dp->d_name, argv[0], taille) != 0)
     72 				continue;
     73 			if (dp->d_name[taille] != '.')
     74 				continue;
     75 			if (strlen(dp->d_name) > NAME_MAX) {
     76 				fprintf(stderr, "execrom: %s: nom trop long\n",
     77 					dp->d_name);
     78 				return 1;
     79 			}
     80 			strcpy(nomrom, dp->d_name);
     81 			closedir(dossier);
     82 			interp = nomrom + taille + 1;
     83 			goto trouve;
     84 		}
     85 
     86 		closedir(dossier);
     87 	}
     88 	/* La ROM n’a pas été trouvée. */
     89 	fprintf(stderr, "execrom: %s n’est pas dans EXECROM_CHEM\n", argv[0]);
     90 	return 1;
     91 
     92 	/* La ROM a été trouvée. */
     93 trouve:
     94 	/* Bâtir le chemin vers la ROM. */
     95 	if ((chemrom = malloc(strlen(nomrom) + strlen(chem) + 2)) == NULL)
     96 		goto erreur;
     97 	strcpy(chemrom, chem);
     98 	strcat(chemrom, "/");
     99 	strcat(chemrom, nomrom);
    100 
    101 	/* Remplir le vecteur d’arguments. */
    102 	if ((args = malloc((argc + 2) * (sizeof(char*)))) == NULL)
    103 		goto erreur;
    104 	args[0] = interp;
    105 	args[1] = chemrom;
    106 	argc = 2;
    107 	while ((args[argc++] = *++argv) != NULL)
    108 		;
    109 
    110 	if (execvp(interp, args) == -1)
    111 		goto erreur;
    112 
    113 	return 0;
    114 
    115 erreur:
    116 	fprintf(stderr, "execrom: %s\n", strerror(errno));
    117 	return 1;
    118 }