2016-04-27 2 views
-1

Je construis un shell personnalisé et je vois quand je compile que usr/include/ctype.h:92 semble avoir besoin de la fonction , mais le compilateur dit que les fonctions en ligne C99 ne sont pas supportées. L'avertissement peut être désactivé avec un paramètre pour le compilateur mais est-ce un bogue qui a besoin d'un correctif?En-tête OpenBSD 5.9 avec fonction en ligne C99

enter image description here

Ceci est mon main.c

#define _XOPEN_SOURCE 500 

#include <sys/stat.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <sys/wait.h> 
#include "openshell.h" 
#include "errors.h" 
#include <errno.h> 
#include <locale.h> 
#include <readline/readline.h> 
#include <getopt.h> 
#include <unistd.h> 
#include <assert.h> 
#include <readline/history.h> 
#ifdef SIGDET 
#if SIGDET == 1 
int isSignal = 1;  /*Termination detected by signals*/ 
#endif 
#endif 
static int sourceCount = 0; 
static FILE *sourcefiles[MAX_SOURCE]; 
/* 
* The special maximum argument value which means that there is 
* no limit to the number of arguments on the command line. 
*/ 
#define INFINITE_ARGS 0x7fffffff 


/* 
* The table of built-in commands. 
* A command is terminated wih an entry containing NULL values. 
*/ 
static const CommandEntry commandEntryTable[] = 
     { 
       { 
         "checkenv", do_checkenv, 1, INFINITE_ARGS, 
         "Check environment variables", 
         "" 
       }, 

       { 
         "add2path", do_add2path, 3, INFINITE_ARGS, 
         "do_add2path", 
         "[txp]v arFileName fileName ..." 
       }, 

       { 
         "cd",  do_cd,  1, 2, 
         "Change current directory", 
         "[dirName]" 
       }, 


       { 
         "exit",  do_exit,  1, 2, 
         "Exit from shell", 
         "[exit value]" 
       }, 


       { 
         "help",  do_help,  1, 2, 
         "Print help about a command", 
         "[word]" 
       }, 

       { 
         "kill",  do_kill,  2, INFINITE_ARGS, 
         "Send a signal to the specified process", 
         "[-sig] pid ..." 
       }, 


       { 
         NULL,  0,   0, 0, 
         NULL, 
         NULL 
       } 
     }; 

struct command { 
    char *const *argv; 
}; 
char** str_split(char* a_str, const char a_delim) 
{ 
    char** result = 0; 
    size_t count  = 0; 
    char* tmp  = a_str; 
    char* last_comma = 0; 
    char delim[2]; 
    delim[0] = a_delim; 
    delim[1] = 0; 

    /* Count how many elements will be extracted. */ 
    while (*tmp) 
    { 
     if (a_delim == *tmp) 
     { 
      count++; 
      last_comma = tmp; 
     } 
     tmp++; 
    } 

    /* Add space for trailing token. */ 
    count += last_comma < (a_str + strlen(a_str) - 1); 

    /* Add space for terminating null string so caller 
     knows where the list of returned strings ends. */ 
    count++; 

    result = malloc(sizeof(char*) * count); 

    if (result) 
    { 
     size_t idx = 0; 
     char* token = strtok(a_str, delim); 

     while (token) 
     { 
      assert(idx < count); 
      *(result + idx++) = strdup(token); 
      token = strtok(0, delim); 
     } 
     assert(idx == count - 1); 
     *(result + idx) = 0; 
    } 

    return result; 
} 
char ** stripped; 
char ** create_pipeline(int argc, char ** argv) { 
    if(!strstr(argv[argc], "|")) { /* && ! isBetweenquotes*/ 
     stripped = argv; 
     return stripped; 

    } 
    else { 
    stripped = argv; 
    return create_pipeline(argc, argv); 
    } 
} 

static int runCmd(const char *cmd) { 
    const char *cp; 
    pid_t pid; 
    int status; 
    struct command shellcommand[4]; 
    char **argv = 0; 
    int argc = 1; 
    bool pipe = false; 
    char *command[40]; 
    char *cmd2[20] = {"cmd2", 0}; 
    int numberofpipelines = 0; 
    unsigned long i3 = 0; 
    unsigned long i2 = 0; 
    unsigned long i1 = 0; 
    unsigned long n = 0; 
    char *string; 
    char *string1; 
    int max_args = 1; /* there's at least one argument or we wouldn't reach this */ 
    cmd2[0] = NULL; 
    cmd2[1] = NULL; 
    cmd2[2] = NULL; 
    command[0] = NULL; 
    command[1] = NULL; 
    command[3] = NULL; 
    char *string2 = NULL; 
    char** tokens; 
    for (cp = cmd; *cp; cp++) { 
     if ((*cp >= 'a') && (*cp <= 'z')) { 
      continue; 
     } 
     if ((*cp >= 'A') && (*cp <= 'Z')) { 
      continue; 
     } 
     if (isDecimal(*cp)) { 
      continue; 
     } 
     if (isBlank(*cp)){ 
      continue; 
     } 
     if ((*cp == '.') || (*cp == '/') || (*cp == '-') || 
      (*cp == '+') || (*cp == '=') || (*cp == '_') || 
      (*cp == ':') || (*cp == ',') || (*cp == '\'') || 
      (*cp == '"')) { 
      continue; 
     } 
    } 
    makeArgs(cmd, &argc, (const char ***) &argv, pipe); 
    char a[20] = {0}; 
    if (sscanf(cmd, "%*[^']'%[^']'", a) == 1) { 
     printf("<undefined>"); 
    } 


    char cmdtmp[75]; 
    strcpy(cmdtmp, cmd); 

    tokens = str_split(cmdtmp, '|'); 

    if (tokens) 
    { 
     int i; 
     for (i = 0; *(tokens + i); i++) 
     { 
      printf("month=[%s]\n", *(tokens + i)); 
      free(*(tokens + i)); 
     } 
     printf("\n"); 
     free(tokens); 
    } 
    for (int i = 0; i < argc; i++) { 
     if (argv[i] != NULL && strstr(argv[i], "|")) { 




      numberofpipelines++; 
      char subbuff[40]; 
      i1 = 0; 
      i2 = 0; 
      i3 = 0; 
      subbuff[0]='\0'; 
      string = strstr(argv[i], "|"); 
      if (string != NULL) { 
       i3 = string - argv[i]; 
       printf("**** is null ***"); 
       cmd2[1] = argv[argc - 1]; 
      } 
      string1 = strstr(&argv[i][i3 + 2], "|"); 
      if (string1 != NULL) { 
       i2 = string1 - argv[i3 + 1]; 
       printf("i2: %lu", i2); 
      } else { 
       char *found3 = strstr(&argv[i][i3 + 1], " "); 
       if (found3 != NULL) {} 
       string2 = strstr(argv[1], "|"); 
       if (string2 != NULL) { 
        i1 = string2 - argv[1]; 
       } 
       n = strlen(argv[1]) - i1; 
       if (argc > 2) { 
        memcpy(subbuff, &argv[i][i3 + 1], n - 1); 
        subbuff[n - 1] = '\0'; 
        cmd2[0] = subbuff; 
        cmd2[1] = argv[argc - 1]; 
       } else { 
        memcpy(subbuff, &argv[i][i3 + 1], n); 
        subbuff[n] = '\0'; 
        cmd2[0] = subbuff; 
        cmd2[1] = argv[argc - 1]; 
       } 
       argc++; 
       argv[i + 1] = subbuff; 
       command[i] = "<undefined>"; 
       argv[i + 2] = NULL; 
       max_args = i; 
      } 
     } 
     if (argv[i] != NULL) { 
      if (i < max_args) { 
       command[i] = argv[i]; 
       command[i+1] = 0; 
       max_args++; 
       cmd2[1] = argv[argc - 1]; 
      } else { 
       command[max_args] = argv[max_args]; 
       command[max_args+1] = 0; 
       cmd2[1] = argv[argc - 1]; 
      } 
     } 
     if (argv[i] != NULL) { 
      char *p = strchr(argv[i], '|'); 
      if (!p) { 
       /* deal with error:/not present" */; 
      } else { 
       *p = 0; 
      } 
     } 

    } 
    dump_argv((const char *) "d", argc, argv); 
/* makeArgs(cmd, &argc, &argv, pipe);*/ 
/* command[2]= 0;*/ 
    shellcommand[0].argv = command; 
    shellcommand[1].argv = cmd2; 
    pid = fork(); 
    if (pid < 0) { 
     perror("fork failed"); 
     return -1; 
    } 
    /* If we are the child process, then go execute the program.*/ 
    if (pid == 0) { 
     /* spawn(cmd);*/ 
     fork_pipes(numberofpipelines, shellcommand); 
    } 
    /* 
    * We are the parent process. 
    * Wait for the child to complete. 
    */ 
    status = 0; 
    while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR)); 
    if (pid < 0) { 
     fprintf(stderr, "Error from waitpid: %s", strerror(errno)); 
     return -1; 
    } 
    if (WIFSIGNALED(status)) { 
     fprintf(stderr, "pid %ld: killed by signal %d\n", 
       (long) pid, WTERMSIG(status)); 

     return -1; 
    } 
    return WEXITSTATUS(status); 
} 

/* The shell performs wildcard expansion on each token it extracts while parsing the command line. 
* Oftentimes, globbing will obviously not do anything (for example, ls just returns ls). 
* When you want nullglob behavior you'll have to know whether the glob function actually found any glob characters, though 
*/ 
static void expandVariable(char *shellcommand) { 
    char mystring[CMD_LEN]; 
    char *cp; 
    char *ep; 

    strcpy(mystring, shellcommand); 
    cp = strstr(mystring, "$("); 
    if (cp) { 
     *cp++ = '\0'; 
     strcpy(shellcommand, mystring); 
     ep = ++cp; 
     while (*ep && (*ep != ')')) ep++; 
     if (*ep == ')') *ep++ = '\0'; 
     cp = getenv(cp); 
     if (cp) strcat(shellcommand, cp); 
     strcat(shellcommand, ep); 
    } 
    return; 
} 

int do_help(int argc, const char **argv) { 
    const CommandEntry *entry; 
    const char *str; 

    str = NULL; 

    if (argc == 2) 
     str = argv[1]; 

    /* 
    * Check for an exact match, in which case describe the program. 
    */ 
    if (str) { 
     for (entry = commandEntryTable; entry->name; entry++) { 
      if (strcmp(str, entry->name) == 0) { 
       printf("%s\n", entry->description); 

       printf("usage: %s %s\n", entry->name, 
         entry->usage); 

       return 0; 
      } 
     } 
    } 

    /* 
    * Print short information about commands which contain the 
    * specified word. 
    */ 
    for (entry = commandEntryTable; entry->name; entry++) { 
     if ((str == NULL) || (strstr(entry->name, str) != NULL) || 
      (strstr(entry->usage, str) != NULL)) { 
      printf("%-10s %s\n", entry->name, entry->usage); 
     } 
    } 

    return 0; 
} 

/* 
* Try to execute a built-in command. 
* Returns TRUE if the command is a built in, whether or not the 
* command succeeds. Returns FALSE if this is not a built-in command. 
*/ 
bool exec_builtin(const char *cmd) { 
    const char *endCmd; 
    const CommandEntry *entry; 
    int argc; 
    const char **argv; 
    char cmdName[CMD_LEN]; 

    /* 
    * Look for the end of the command name and then copy the 
    * command name to a buffer so we can null terminate it. 
    */ 
    endCmd = cmd; 

    while (*endCmd && !isBlank(*endCmd)) 
     endCmd++; 

    memcpy(cmdName, cmd, endCmd - cmd); 
    cmdName[endCmd - cmd] = '\0'; 

    /* 
    * Search the command table looking for the command name. 
    */ 
    for (entry = commandEntryTable; entry->name != NULL; entry++) { 
     if (strcmp(entry->name, cmdName) == 0) 
      break; 
    } 

    /* 
    * If the command is not a built-in, return indicating that. 
    */ 
    if (entry->name == NULL) { 
     return false; 
    } 

    bool bo = false; 
    /* 
    * The command is a built-in. 
    * Break the command up into arguments and expand wildcards. 
    */ 
    if (!makeArgs(cmd, &argc, &argv, bo)) { 
     return true; 
    } 

    /* 
    * Give a usage string if the number of arguments is too large 
    * or too small. 
    */ 
    if ((argc < entry->minArgs) || (argc > entry->maxArgs)) { 
     fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage); 
     return true; 
    } 

    /* 
    * Call the built-in function with the argument list. 
    */ 
    entry->func(argc, argv); 
    return true; 
} 


/* 
* Parse and execute one null-terminated command line string. 
* This breaks the command line up into words, checks to see if the 
* command is an alias, and expands wildcards. 
*/ 
int command(const char *cmd) { 
    const char *endCmd; 
    char cmdName[CMD_LEN]; 
    freeChunks(); 

    /* 
    * Skip leading blanks. 
    */ 
    while (isBlank(*cmd)) 
     cmd++; 
    /* 
    * If the command is empty or is a comment then ignore it. 
    */ 
    if ((*cmd == '\0') || (*cmd == '#')) 
     return 0; 
    /* 
    * Look for the end of the command name and then copy the 
    * command name to a buffer so we can null terminate it. 
    */ 
    endCmd = cmd; 
    while (*endCmd && !isBlank(*endCmd)) 
     endCmd++; 

    memcpy(cmdName, cmd, endCmd - cmd); 
    cmdName[endCmd - cmd] = '\0'; 
    /* 
    * Expand simple environment variables 
    */ 
    while (strstr(cmd, "$(")) expandVariable((char *) cmd); 
    /* 
    * Now look for the command in the builtin table, and execute 
    * the command if found. 
    */ 
    if (exec_builtin(cmd)) { 
     return 0; 
    } 
    /* 
    * The command is not a built-in, so run the program along 
    * the PATH list. 
    */ 
    return runCmd(cmd); 
} 

/* 
* Execute the specified file or program 
* A null name pointer indicates to read from stdin. 
*/ 

int exec_program(const char *name) { 
    FILE *fp; 
    int r = 0; 
    char *input, shell_prompt[100]; 
    if (sourceCount >= MAX_SOURCE) { 
     fprintf(stderr, "Too many source files\n"); 
     return 1; 
    } 
    fp = stdin; 
    if (name) { 
     fp = fopen(name, "r"); 

     if (fp == NULL) { 
      perror(name); 

      return 1; 
     } 
    } 
    sourcefiles[sourceCount++] = fp; 
    setlocale(LC_CTYPE, ""); 
    /*Configure readline to auto-complete paths when the tab key is hit.*/ 
    rl_bind_key('\t', rl_complete); 
    /*stifle_history(7);*/ 
    for (; ;) { 
     /* Create prompt string from user name and current working directory.*/ 
     snprintf(shell_prompt, sizeof(shell_prompt), "%s:%s $ ", getenv("USER"), getcwd(NULL, 1024)); 
     // Display prompt and read input (NB: input must be freed after use)... 
     input = readline(shell_prompt); 
     // Check for EOF. 
     if (!input) 
      break; 
     add_history(input); 
     r = command(input); 
     free(input); 
    } 
    return r; 
} 

static struct option long_options[] = { 
     {"with_param", 1, 0, 'p'}, 
     {"version", 0, 0, 'v'}, 
     {"help",  0, 0, 'h'}, 
     {0,   0, 0, 0} 
}; 

char s[] = "Interrupt\n"; 

void int_handler(int signum) { 
    if (write(fileno(stdin), s, sizeof s - 1)) { } else { } 
    if (signum) { if (false); } else { } 
} 

int main(int argc, char *argv[]) { 
    struct sigaction sh; 

    sh.sa_handler = int_handler; 
    sigemptyset(&sh.sa_mask); 
    sh.sa_flags = 0; 
    sigaction(SIGINT, &sh, NULL); 

    sourceCount = 0; 
    const char *commandFile; 
    commandFile = NULL; 
    char *pathValue; 
    int option; 
    sh.sa_handler = int_handler; 
    sigemptyset(&sh.sa_mask); 
    sh.sa_flags = 0; 
    sigaction(SIGINT, &sh, NULL); 
    int option_index = 0; 
    while (1) { 
     option_index = 0; 
     option = getopt_long(argc, argv, "p:vh", 
          long_options, &option_index); 
     if (option == -1) 
      break; 
     switch (option) { 
      case 'p': { 
       /* store_parameter(optarg); */ 
       break; 
      } 
      case 'v': { 
       printf("OpenShell version 0.1(a)\n"); 
       printf("Version: %s\n", VERSION); 
       exit(EXIT_SUCCESS); 

      } 
      case 'h': { 
       printf("Usage: ./shell\n"); 
       /*print_help();*/ 
       exit(EXIT_SUCCESS); 

      } 
      default: { 
       /*    fprintf(stderr, "Error (%s): unrecognized option.\n", __FUNCTION__);*/ 
       /* print_help();*/ 
       return 1;/*RETURN_FAILURE;*/ 

      } 
     } /* end switch */ 
    } 
    /* get the PATH environment to find if less is installed */ 
    pathValue = getenv("PATH"); 
    if (!pathValue || getenv("PATH") == NULL) { 
     printf("'%s' is not set.\n", "PATH"); 
     /* Default our path if it is not set. */ 
     putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc"); 
    } 
    else { 
     printf("'%s' is set to %s.\n", "PATH", pathValue); 
    } 
    exec_program(commandFile); 
    return (0); 
} 

Mon makefile:

CC = gcc 
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) 
CFLAGS := $(CFLAGS) -L/usr/local/include/ -L/usr/include -pedantic -std=c99 -Wall -O3 -g -DVERSION=\"$(GIT_VERSION)\" -ledit -lncurses 

LDIRS = -L/usr/local/lib -L/usr/lib 
LIBS =su -lcurses 

shell: main.o 
    $(CC) -o shell main.o errors.c util.c pipeline.c -ledit -lncurses -lcurses 

main.o: main.c errors.c util.c 
USERNAME := $(shell whoami >> username.txt) 
GIT:= $(shell head -n -1 openshell.h > temp.txt ; mv temp.txt openshell.h;git describe --abbrev=4 --dirty --always --tags > VERSION; echo "\#define VERSION \"$(GIT_VERSION)\"" >> openshell.h) 

.PHONY: clean 
clean: 
    rm -f *.o 
+1

Pouvez-vous publier votre fichier 'main.c'? – dreamlax

Répondre

0

Vous devez compiler avec C99 ou C11, et les drapeaux à gcc:

gcc -std=c99 

ou

gcc -std=c11 
+1

Vous ne devriez pas avoir besoin de drapeaux spéciaux pour pouvoir inclure 'ctype.h'. – dreamlax

+1

Le problème ne concerne pas 'ctype.h', il s'agit des fonctions' inline'. – fluter

+1

La capture d'écran montre que le compilateur se plaint de l'utilisation de fonctions en ligne dans 'ctype.h'. – dreamlax