summaryrefslogtreecommitdiff
path: root/config.c
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-09-14 17:57:07 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-09-14 17:57:07 +0100
commite1f41810ac85a0d210062ed33f43938dc4b03be4 (patch)
tree24e100886b063dfe8aa49d6881070b9e238296c4 /config.c
parente546de81cbecac2b02d29a02d6c6fd7d0785d739 (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.c181
1 files changed, 177 insertions, 4 deletions
diff --git a/config.c b/config.c
index cea404c..842f389 100644
--- a/config.c
+++ b/config.c
@@ -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"