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 }