diff options
| author | Luke Bratch <luke@bratch.co.uk> | 2019-09-14 17:57:07 +0100 | 
|---|---|---|
| committer | Luke Bratch <luke@bratch.co.uk> | 2019-09-14 17:57:07 +0100 | 
| commit | e1f41810ac85a0d210062ed33f43938dc4b03be4 (patch) | |
| tree | 24e100886b063dfe8aa49d6881070b9e238296c4 /config.c | |
| parent | e546de81cbecac2b02d29a02d6c6fd7d0785d739 (diff) | |
Implement arrays in the configuration file and start using them to allow for multiple connect commands.
Diffstat (limited to 'config.c')
| -rw-r--r-- | config.c | 181 | 
1 files changed, 177 insertions, 4 deletions
| @@ -25,7 +25,7 @@ int getconfstr(char *confname, char *filename, char* dest) {    char str[MAXCHAR];    int found = 0; // Have we found the configuration option? -  // Set strings to zero-length to begin +  // Set string to zero-length to begin    dest[0] = '\0';    // Length of requested configuration option name @@ -105,6 +105,165 @@ int getconfstr(char *confname, char *filename, char* dest) {    return 1;  } +// Populates 'dest' with the values of the configuration array option +// with name 'confname' from configuration file 'filename'. +// Returns 1 on success, 0 on reading no values, or -1 on an error. +// On error, dest[0] is set to the error string for later retrieval. +int getconfarr(char *confname, char *filename, char dest[MAXCONFARR][MAXDATASIZE]) { +  debugprint(DEBUG_FULL, "getconfarr(): '%s', '%s' and a dest array.\n", confname, filename); + +  FILE *fp; +  char line[MAXCHAR]; +  int found = 0; // Have we found the configuration option? +  int valuecount = 0; // Which element in the configuration array we are on + +  // Set strings to zero-length to begin +  for (int i = 0; i < MAXCONFARR; i++) { +    dest[i][0] = '\0'; +  } + +  // Length of requested configuration array name +  long int namelen = strlen(confname); + +  fp = fopen(filename, "r"); + +  if (fp == NULL) { +    debugprint(DEBUG_CRIT, "error: could not open configuration file '%s'.\n", filename); +    exit(1); +  } +  // Loop through the whole file, looking for the requested configuration array +  while (fgets(line, MAXCHAR, fp) != NULL) { +    // Don't bother with any of this if this line is a comment +    int comment = 0; +    for (size_t i = 0; i < strlen(line); i++) { +      // Ignore spaces/tabs +      if (line[i] == ' ' || line[i] == '\t') { +        continue; +      } else if (line[i] == '#') { +        // If it's a comment, ignore the line +        comment = 1; +        break; +      } else { +        // Found something else before a comment, so carry on +        break; +      } +    } + +    if (comment) { +      continue; +    } + +    // If we haven't found our array yet, try to find the opening line +    if (!found) { +      char substr[MAXCHAR]; + +      // Check if the next character after the length of the requested array +      // name is an equals sign, a space, or a tab +      if (line[namelen] != '=' && line[namelen] != ' ' && line[namelen] != '\t') { +        // If it isn't this can't have been our array +        continue; +      } + +      // Copy the number of characters that the requested array name is long +      // to a temporary string +      strncpy(substr, line, namelen); +      substr[namelen] = '\0'; + +      // If the resulting temporary string contains the requested array name, +      // we have found our configuration array +      if (strstr(substr, confname)) { +        // Make sure it is a valid start of array line +        for (size_t i = namelen; i < strlen(line); i++) { +          if (line[i] == ' ' || line[i] == '\t' || line[i] == '=') { +            // Ignore spaces, tabs and equals signs +            continue; +          } else if (line[i] == '{') { +            // Success, found an opening brace +            // Ignore anything else on this line +            found = 1; +            break; +          } else { +            // Unexpected character found, return failure +            snprintf(dest[0], MAXDATASIZE, "Unexpected character '%c' found on configuration array opening line for '%s'.\n", line[i], confname); +            fclose(fp); +            return -1; +          } +        } +      } +    // If we have found our array, extract the value from each line in it +    } else { +      int valuelen = 0; +      int inquotes = 0; +      for (size_t i = 0; i < strlen(line); i++) { +        // If we've on the closing brace line, then we're done +        if (line[i] == '}') { +          for (int i = 0; i < valuecount; i++) { +            debugprint(DEBUG_FULL, "getconfstr(): returning '%s'.\n", dest[i]); +          } + +          // Close fine and return success (or 0 if no values found in an otherwise valid array) +          fclose(fp); +          if (valuecount) { +            return 1; +          } else { +            return 0; +          } +        } + +        // If not in the quotes yet +        if (!inquotes) { +          // Skip over initial spaces and tabs +          if (line[i] == ' ' || line[i] == '\t') { +            continue; +          } else if (line[i] == '"') { +            // Quotes found, we're now reading the value +            inquotes = 1; +            continue; +          } else { +            // Unexpected character found, return failure +            snprintf(dest[0], MAXDATASIZE, "Unexpected character '%c' found before opening quotes on array line for '%s'.\n", line[i], confname); +            fclose(fp); +            return -1; +          } +          // If inside the quotes (so, we've got to the actual value) +        } else if (inquotes) { +          // If we're on the last character and it isn't a closing quote, something is wrong +          if (i == strlen(line) - 1 && line[i] != '"') { +            snprintf(dest[0], MAXDATASIZE, "Reached end of line without finding closing quotes on array line for '%s'.\n", confname); +            fclose(fp); +            return -1; +          } + +          // If we've found too many values, return an error +          if (valuecount > MAXCONFARR) { +            snprintf(dest[0], MAXDATASIZE, "Too many elements defined for configuration array '%s', maximum number is '%d'.\n", confname, MAXCONFARR); +            fclose(fp); +            return -1; +          } + +          // Otherwise, copy everything that isn't the closing quotes to the current element in the dest array +          if (line[i] != '"') { +            dest[valuecount][valuelen] = line[i]; +            valuelen++; +            continue; +          } else { +            // When we find the closing quotes, the value is read, so terminate the dest array element string +            dest[valuecount][valuelen] = '\0'; +            // We're done with this value, ignore anything that may be after the closing quotes on this line +            valuecount++; +            break; +          } +        } +      } +    } +  } + +  // If we get this far, then something went wrong +  snprintf(dest[0], MAXDATASIZE, "getconfarr(): didn't find any configuration array for '%s'.\n", confname); +  fclose(fp); +  return 0; +} +  // Returns the value of the configuration option with name  // 'confname' from configuration file 'filename'.  // Sets errno to 0 on success, or ECONFINT if it fails, in which case the return value is undefined. @@ -153,11 +312,22 @@ int createconfigfile(char *filename) {    char *string =    "# blabouncer configuration file\n"    "#\n" -  "# Entries must be in the form:\n" +  "# Normal entries must be in the form:\n"    "# option name, space, equals sign, space, double quote, option value, double quote\n"    "# e.g.\n"    "# realname = \"Mr Bla Bouncer\"\n"    "#\n" +  "# Array entries must be in the form:\n" +  "# option name, space, equals sign, space, open brace\n" +  "# (optional indentation,) double quote, element value, double quoute\n" +  "# (optional multiple values to be repeated after the first one(s))\n" +  "# close brace\n" +  "# e.g.\n" +  "# connectcommands = {\n" +  "#   \"PRIVMSG NickServ IDENTIFY bananas\"\n" +  "#   \"PRIVMSG myfriend I'm online!\"\n" +  "# }\n" +  "#\n"    "# Shell expansion is not supported, so do not try and specify e.g.\n"    "# \"~/.blabouncer/\" or \"$HOME/.blabouncer/\", instead use \"/home/foo/.blabouncer\"\n"    "#\n" @@ -210,8 +380,11 @@ int createconfigfile(char *filename) {    "# Real IRC server password\n"    "#ircserverpassword = \"apples\"\n"    "\n" -  "# Command to send to the server upon completing registration (e.g. a NickServ password)\n" -  "#connectcommand \"PRIVMSG NickServ IDENTIFY bananas\"\n" +  "# Command(s) to send to the server upon completing registration (e.g. a NickServ password)\n" +  "#connectcommands = {\n" +  "#  \"PRIVMSG NickServ IDENTIFY bananas\"\n" +  "#  \"PRIVMSG myfriend I'm online!\"\n" +  "#}\n"    "\n"    "# Base directory (defaults to $HOME/.blabouncer/)\n"    "# Things such as the logs directory will be placed below this\n" | 
