c

How can I get a string representation for the error return values of wordexp(3) in C?


I'm writing a program where I need to do some shell path expansion, and I've decided to use wordexp(3) for this. Since the argument I'm giving to it is user-provided, I would like to present a relevant error message in the case of a non-zero return value. However, I can't seem to figure out how I would do this. Based on my reading of the manual page for this function, it doesn't seem to make use of errno, so I can't use perror(). I can't print the constant values it provides either since they just are integers at runtime.

How can I get a string representation of the error return values?


Solution

  • Regarding printing some enum error codes that are essentially just integers: just make a string table of error messages and print the one you want based on the error code.


    Solution 1

    It could be semi-automated somewhat by using "X macros":

    #include <wordexp.h>
    
    #define WORDEXP_RESULT(X)                 \
    /*  code          custom error message */ \
      X(WRDE_BADCHAR, "Bad char is bad!")     \
      X(WRDE_BADVAL,  "Bad value is bad!")    \
      // and so on...
    

    Then you'd call the function and check the result, for example with a switch:

    int result = wordexp(...);
    switch(result)
    {
      case 0: /* ok */ break;
      WORDEXP_RESULT(WORDEXP_ERR_CASE)
    };
    

    Where the macro list boils down to some convenient macro:

    #define WORDEXP_ERR_CASE(val, str)                 \
      case (val):                                      \
      {                                                \
        fprintf(stderr,                                \
                "Error: wordexp failed. Code: %s. %s", \
                #val, str);                            \
        break;                                         \
      }
    

    Output from this will look like:

    Error: wordexp failed. Code: WRDE_BADCHAR. Bad char is bad!
    

    The advantage of the X macro here is that you get a direct coupling between the wordexp.h error codes and your error messages, plus macros mean we can "stringificate" the enumeration constants.


    Solution 2

    Although I cheated and took a peek at what these enums expand to. It turns out they are adjacent number from 1 to upward. So we could actually get rid of the switch without getting a huge string table. And at the same time write something more readable than X macros:

    if(result != 0)
    {
      const char* wordexp_errmsg[] = 
      {
        [WRDE_BADCHAR] = "Bad char is bad!",
        [WRDE_BADVAL]  = "Bad value is bad!"
      };
    
      fprintf(stderr, "Error: wordexp failed. %s\n", wordexp_errmsg[result]);
    }
    

    This has a coupling between error codes and strings too, but we lose the handy stringification of the enumeration constants themselves.