+ * Read in and handle a configuration file.
+ *
+ * @param File Name of the configuration file.
+ * @param fd File descriptor already opened for reading.
+ */
+static void
+Read_Config_File(const char *File, FILE *fd)
+{
+ char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
+ int i, line = 0;
+ size_t count;
+
+ /* Read configuration file */
+ section[0] = '\0';
+ while (true) {
+ if (!fgets(str, sizeof(str), fd))
+ break;
+ ngt_TrimStr(str);
+ line++;
+
+ /* Skip comments and empty lines */
+ if (str[0] == ';' || str[0] == '#' || str[0] == '\0')
+ continue;
+
+ if (strlen(str) >= sizeof(str) - 1) {
+ Config_Error(LOG_WARNING, "%s, line %d too long!",
+ File, line);
+ continue;
+ }
+
+ /* Is this the beginning of a new section? */
+ if ((str[0] == '[') && (str[strlen(str) - 1] == ']')) {
+ strlcpy(section, str, sizeof(section));
+ if (strcasecmp(section, "[GLOBAL]") == 0
+ || strcasecmp(section, "[LIMITS]") == 0
+ || strcasecmp(section, "[OPTIONS]") == 0
+#ifdef SSL_SUPPORT
+ || strcasecmp(section, "[SSL]") == 0
+#endif
+ )
+ continue;
+
+ if (strcasecmp(section, "[SERVER]") == 0) {
+ /* Check if there is already a server to add */
+ if (New_Server.name[0]) {
+ /* Copy data to "real" server structure */
+ assert(New_Server_Idx > NONE);
+ Conf_Server[New_Server_Idx] =
+ New_Server;
+ }
+
+ /* Re-init structure for new server */
+ Init_Server_Struct(&New_Server);
+
+ /* Search unused item in server configuration structure */
+ for (i = 0; i < MAX_SERVERS; i++) {
+ /* Is this item used? */
+ if (!Conf_Server[i].name[0])
+ break;
+ }
+ if (i >= MAX_SERVERS) {
+ /* Oops, no free item found! */
+ Config_Error(LOG_ERR,
+ "Too many servers configured.");
+ New_Server_Idx = NONE;
+ } else
+ New_Server_Idx = i;
+ continue;
+ }
+
+ if (strcasecmp(section, "[CHANNEL]") == 0) {
+ count = array_length(&Conf_Channels,
+ sizeof(struct
+ Conf_Channel));
+ if (!array_alloc
+ (&Conf_Channels,
+ sizeof(struct Conf_Channel), count)) {
+ Config_Error(LOG_ERR,
+ "Could not allocate memory for new operator (line %d)",
+ line);
+ }
+ continue;
+ }
+
+ if (strcasecmp(section, "[OPERATOR]") == 0) {
+ count = array_length(&Conf_Opers,
+ sizeof(struct Conf_Oper));
+ if (!array_alloc(&Conf_Opers,
+ sizeof(struct Conf_Oper),
+ count)) {
+ Config_Error(LOG_ERR,
+ "Could not allocate memory for new channel (line &d)",
+ line);
+ }
+ continue;
+ }
+
+ Config_Error(LOG_ERR,
+ "%s, line %d: Unknown section \"%s\"!",
+ File, line, section);
+ section[0] = 0x1;
+ }
+ if (section[0] == 0x1)
+ continue;
+
+ /* Split line into variable name and parameters */
+ ptr = strchr(str, '=');
+ if (!ptr) {
+ Config_Error(LOG_ERR, "%s, line %d: Syntax error!",
+ File, line);
+ continue;
+ }
+ *ptr = '\0';
+ var = str;
+ ngt_TrimStr(var);
+ arg = ptr + 1;
+ ngt_TrimStr(arg);
+
+ if (strcasecmp(section, "[GLOBAL]") == 0)
+ Handle_GLOBAL(File, line, var, arg);
+ else if (strcasecmp(section, "[LIMITS]") == 0)
+ Handle_LIMITS(File, line, var, arg);
+ else if (strcasecmp(section, "[OPTIONS]") == 0)
+ Handle_OPTIONS(File, line, var, arg);
+#ifdef SSL_SUPPORT
+ else if (strcasecmp(section, "[SSL]") == 0)
+ Handle_SSL(File, line, var, arg);
+#endif
+ else if (strcasecmp(section, "[OPERATOR]") == 0)
+ Handle_OPERATOR(File, line, var, arg);
+ else if (strcasecmp(section, "[SERVER]") == 0)
+ Handle_SERVER(File, line, var, arg);
+ else if (strcasecmp(section, "[CHANNEL]") == 0)
+ Handle_CHANNEL(File, line, var, arg);
+ else
+ Config_Error(LOG_ERR,
+ "%s, line %d: Variable \"%s\" outside section!",
+ File, line, var);
+ }
+}
+
+/**
+ * Check whether a string argument is "true" or "false".