conf-file.c (5749B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "config.h" 21 22#include "conf.h" 23#include "conf-file.h" 24#include "conf-parse.h" 25 26#include <guacamole/client.h> 27#include <guacamole/mem.h> 28#include <guacamole/string.h> 29 30#include <errno.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <unistd.h> 35 36#include <sys/types.h> 37#include <sys/stat.h> 38#include <fcntl.h> 39 40/** 41 * Updates the configuration with the given parameter/value pair, flagging 42 * errors as necessary. 43 */ 44static int guacd_conf_callback(const char* section, const char* param, const char* value, void* data) { 45 46 guacd_config* config = (guacd_config*) data; 47 48 /* Network server options */ 49 if (strcmp(section, "server") == 0) { 50 51 /* Bind host */ 52 if (strcmp(param, "bind_host") == 0) { 53 guac_mem_free(config->bind_host); 54 config->bind_host = guac_strdup(value); 55 return 0; 56 } 57 58 /* Bind port */ 59 else if (strcmp(param, "bind_port") == 0) { 60 guac_mem_free(config->bind_port); 61 config->bind_port = guac_strdup(value); 62 return 0; 63 } 64 65 } 66 67 /* Options related to daemon startup */ 68 else if (strcmp(section, "daemon") == 0) { 69 70 /* PID file */ 71 if (strcmp(param, "pid_file") == 0) { 72 guac_mem_free(config->pidfile); 73 config->pidfile = guac_strdup(value); 74 return 0; 75 } 76 77 /* Max log level */ 78 else if (strcmp(param, "log_level") == 0) { 79 80 int level = guacd_parse_log_level(value); 81 82 /* Invalid log level */ 83 if (level < 0) { 84 guacd_conf_parse_error = "Invalid log level. Valid levels are: \"trace\", \"debug\", \"info\", \"warning\", and \"error\"."; 85 return 1; 86 } 87 88 /* Valid log level */ 89 config->max_log_level = level; 90 return 0; 91 92 } 93 94 } 95 96 /* SSL-specific options */ 97 else if (strcmp(section, "ssl") == 0) { 98#ifdef ENABLE_SSL 99 /* SSL certificate */ 100 if (strcmp(param, "server_certificate") == 0) { 101 guac_mem_free(config->cert_file); 102 config->cert_file = guac_strdup(value); 103 return 0; 104 } 105 106 /* SSL key */ 107 else if (strcmp(param, "server_key") == 0) { 108 guac_mem_free(config->key_file); 109 config->key_file = guac_strdup(value); 110 return 0; 111 } 112#else 113 guacd_conf_parse_error = "SSL support not compiled in"; 114 return 1; 115#endif 116 117 } 118 119 /* If still unhandled, the parameter/section is invalid */ 120 guacd_conf_parse_error = "Invalid parameter or section name"; 121 return 1; 122 123} 124 125int guacd_conf_parse_file(guacd_config* conf, int fd) { 126 127 int chars_read; 128 129 char buffer[8192]; 130 int length = 0; 131 132 int line = 1; 133 char* line_start = buffer; 134 int parsed = 0; 135 136 /* Attempt to fill remaining space in buffer */ 137 while ((chars_read = read(fd, buffer + length, sizeof(buffer) - length)) > 0) { 138 139 length += chars_read; 140 141 line_start = buffer; 142 143 /* Attempt to parse entire buffer */ 144 while ((parsed = guacd_parse_conf(guacd_conf_callback, line_start, length, conf)) > 0) { 145 line_start += parsed; 146 length -= parsed; 147 line++; 148 } 149 150 /* Shift contents to front */ 151 memmove(buffer, line_start, length); 152 153 } 154 155 /* Handle parse errors */ 156 if (parsed < 0) { 157 int column = guacd_conf_parse_error_location - line_start + 1; 158 fprintf(stderr, "Parse error at line %i, column %i: %s.\n", 159 line, column, guacd_conf_parse_error); 160 return 1; 161 } 162 163 /* Check for error conditions */ 164 if (chars_read < 0) { 165 fprintf(stderr, "Error reading configuration: %s\n", strerror(errno)); 166 return 1; 167 } 168 169 /* Read successfully */ 170 return 0; 171 172} 173 174guacd_config* guacd_conf_load() { 175 176 guacd_config* conf = guac_mem_alloc(sizeof(guacd_config)); 177 if (conf == NULL) 178 return NULL; 179 180 /* Load defaults */ 181 conf->bind_host = guac_strdup(GUACD_DEFAULT_BIND_HOST); 182 conf->bind_port = guac_strdup(GUACD_DEFAULT_BIND_PORT); 183 conf->pidfile = NULL; 184 conf->foreground = 0; 185 conf->print_version = 0; 186 conf->max_log_level = GUAC_LOG_INFO; 187 188#ifdef ENABLE_SSL 189 conf->cert_file = NULL; 190 conf->key_file = NULL; 191#endif 192 193 /* Read configuration from file */ 194 int fd = open(GUACD_CONF_FILE, O_RDONLY); 195 if (fd > 0) { 196 197 int retval = guacd_conf_parse_file(conf, fd); 198 close(fd); 199 200 if (retval != 0) { 201 fprintf(stderr, "Unable to parse \"" GUACD_CONF_FILE "\".\n"); 202 guac_mem_free(conf); 203 return NULL; 204 } 205 206 } 207 208 /* Notify of errors preventing reading */ 209 else if (errno != ENOENT) { 210 fprintf(stderr, "Unable to open \"" GUACD_CONF_FILE "\": %s\n", strerror(errno)); 211 guac_mem_free(conf); 212 return NULL; 213 } 214 215 return conf; 216 217} 218