bibic

bibliothèques pour l'interpréteur de commande
git clone git://git.asteride.xyz/~ldp/bibic.git
Journaux | Fichiers | Références | LICENCE

bibic.c (3264B)


      1 /*
      2  * Copyright (c) 2023 Selve <selve@asteride.xyz>
      3  *
      4  * Ce fichier fait partie de bibic, publié sous la licence GPLv3 (seulement).
      5  * Consultez le fichier LICENCE ou le site <https://www.gnu.org/licenses/>
      6  * pour plus de détails.
      7  */
      8 
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 #include <unistd.h>
     13 
     14 #include <errno.h>
     15 #include <limits.h>
     16 
     17 #define IC_DEF "/bin/sh" /* interpréteur de commandes par défaut */
     18 
     19 extern char **environ;
     20 
     21 static void utilisation(void);
     22 
     23 int
     24 main(int argc, char **argv)
     25 {
     26 	char *sh;    /* interpéreteur de commande */
     27 	char *var;   /* pointeur vers variable d'environnement */
     28 	char **args; /* arguments à passer à l'interpréteur */
     29 
     30 	if (argc < 2) {
     31 		utilisation();
     32 		return 1;
     33 	}
     34 
     35 	/* création des arguments à fournir à l'interpréteur
     36 	 * 0: nom du script
     37 	 * 1: option pour forcer l'interprétation en entrée standard,
     38 	 *    sert avant tout à indiquer à l'interpréteur de transférer les
     39 	 *    arguments au script
     40 	 * 2: option pour indiquer à l'interpréteur de traiter les arguments qui
     41 	 *    suivent comme des arguments et non comme des options. Nécessaire
     42 	 *    pour qu'il soit possible de fournir des options aux scripts.
     43 	 * …: arguments à fournir au script */
     44 	if ((args = malloc(argc + 2)) == NULL)
     45 		goto erreur;
     46 	args[0]        = argv[1];
     47 	args[1]        = "-si";
     48 	args[2]        = "--";
     49 	args[argc + 1] = NULL;
     50 
     51 	/* copier les arguments */
     52 	while (argc > 2) {
     53 		args[argc] = argv[argc-1];
     54 		argc--;
     55 	}
     56 
     57 	/* POSIX stipule que le chemin contenu dans la variable ENV doit être
     58 	 * absolu. Il faut assembler ce chemin. Ce chemin est formé par la
     59 	 * concaténation du dossier courant, d'une barre oblique (/) et du
     60 	 * fichier dans lequel se trouve le script.
     61 	 * Bien sûr, nul besoin de tout cela si le chemin fourni est déjà un
     62 	 * besoin absolu. */
     63 	if (argv[1][0] != '/') {
     64 		static char  abs[PATH_MAX]; /* chemin absolu */
     65 		size_t       lngr;          /* longueur du chemin */
     66 
     67 		if (getcwd(abs, PATH_MAX) == NULL)
     68 			goto erreur;
     69 		lngr = strlen(abs);
     70 		/* il faut encore ajouter au moins deux caractères au chemin. */
     71 		if (lngr + 2 >= PATH_MAX) {
     72 			errno = ENAMETOOLONG;
     73 			goto erreur;
     74 		}
     75 		abs[lngr++] = '/';
     76 		strncpy(abs + lngr, argv[1], PATH_MAX - lngr);
     77 		/* strncpy remplit le reste du tampon avec des caractères NUL.
     78 		 * si donc le dernier caractère n'est pas NUL, c'est que le
     79 		 * chemin est trop long. */
     80 		if (abs[PATH_MAX - 1] != '\0') {
     81 			errno = ENAMETOOLONG;
     82 			goto erreur;
     83 		}
     84 
     85 		argv[1] = abs;
     86 	}
     87 
     88 	/* BIBIC_SHELL a priorité sur SHELL. Si ni l'une ni l'autre n'existe,
     89 	 * l'interpréteur spécifié par le macro IC_DEF est assigné à sh */
     90 	if ((var = getenv("BIBIC_SHELL")) != NULL ||
     91 	    (var = getenv("SHELL")) != NULL)
     92 		sh = var;
     93 	else
     94 		sh = IC_DEF;
     95 
     96 	/* Si la variable ENV existe déjà, on déplace son contenu vers
     97 	 * BIBIC_ENV, sinon, il faut supprimer BIBIC_ENV pour ne pas que les
     98 	 * programmes sourcent un fichier sans raison. */
     99 	if ((var = getenv("ENV")) != NULL)
    100 		setenv("BIBIC_ENV", var, 1);
    101 	else
    102 		unsetenv("BIBIC_ENV");
    103 	setenv("ENV", argv[1], 1);
    104 
    105 	execve(sh, args, environ);
    106 
    107 erreur:
    108 	perror("bibic");
    109 	return 1;
    110 }
    111 
    112 static void
    113 utilisation(void)
    114 {
    115 	fprintf(stderr, "UTILISATION: bibic [programme] [arg ...]\n");
    116 }