summaryrefslogtreecommitdiff
path: root/lib/config.sh
blob: 0b344e712b931670f79c83d7ad8743fcfb8a7c6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/bin/bash
# -*- coding: utf-8 -*-
###########################################################################
#                                                                         #
#  envbot - an IRC bot in bash                                            #
#  Copyright (C) 2007-2008  Arvid Norlander                               #
#                                                                         #
#  This program is free software: you can redistribute it and/or modify   #
#  it under the terms of the GNU General Public License as published by   #
#  the Free Software Foundation, either version 3 of the License, or      #
#  (at your option) any later version.                                    #
#                                                                         #
#  This program is distributed in the hope that it will be useful,        #
#  but WITHOUT ANY WARRANTY; without even the implied warranty of         #
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
#  GNU General Public License for more details.                           #
#                                                                         #
#  You should have received a copy of the GNU General Public License      #
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.  #
#                                                                         #
###########################################################################
#---------------------------------------------------------------------
## Configuration management
#---------------------------------------------------------------------

#---------------------------------------------------------------------
## Rehash config file.
## @Type API
## @return 0 Success.
## @return 2 Not same config version.
## @return 3 Failed to source. The bot should not be in an undefined state.
## @return 4 Config validation on faked source failed. The bot should not be in an undefined state.
## @return 5 Failed to source. The bot may be in an undefined state.
## @Note If config validation fails at REAL source, the bot may quit. However this should never happen.
#---------------------------------------------------------------------
config_rehash() {
	local new_conf_ver="$(grep -E '^config_version=' "$config_file")"
	if ! [[ $new_conf_ver =~ ^config_version=$config_current_version ]]; then
		log_error "REHASH: Not same config version. Rehash aborted."
		return 2
	fi
	# Try sourceing in a subshell first to catch errors
	# without causing bot to break
	( source "$config_file" )
	if [[ $? -ne 0 ]]; then
		log_error "REHASH: Failed faked source. Rehash aborted. (TIP: Check for syntax errors in config and any message above this message.)"
		return 3
	fi
	# HACK: Subshell, then unset all but two config_ variables (one is readonly, the other is needed to validate)
	# Then source config file and run validation on it.
	( unset -v $(sed 's/ *config_current_version */ /g;s/ *config_file */ /g' <<<"${!config_*}")
		source "$config_file"
		config_validate && config_validate_transport )
	if [[ $? -ne 0 ]]; then
		log_error "REHASH: Failed config validation on new config. Rehash aborted."
		return 4
	fi
	# Source for real if that worked
	source "$config_file"
	if [[ $? -ne 0 ]]; then
		log_error "REHASH: Failed real source. BOT MAY BE IN UNDEFINED STATE."
		return 5
	fi
	# Lets force command line -v, it may have been overwritten by config.
	if [[ $force_verbose -eq 1 ]]; then
		config_log_stdout='1'
	fi
	local status
	modules_load_from_config
	for module in $modules_loaded; do
		module_${module}_REHASH
		status=$?
		if [[ $status -eq 1 ]]; then
			log_error "Rehash of ${module} failed, trying to unload it."
			modules_unload "${module}" || {
				log_fatal "Unloading of ${module} after failed rehash failed."
				bot_quit "Fatal error in unload of module that failed to rehash"
			}
		fi
		if [[ $status -eq 2 ]]; then
			log_fatal "Rehash of ${module} failed in a FATAL way. Quitting"
			bot_quit "Fatal error in rehash of module"
		fi
	done
	log_info_stdout "Rehash successful"
}


###########################################################################
# Internal functions to core or this file below this line!                #
# Module authors: go away                                                 #
###########################################################################

#---------------------------------------------------------------------
## This will call logging if logging is setup,
## otherwise just print to STDOUT, with prefix
## @Type Private
#---------------------------------------------------------------------
config_dolog_fatal() {
	if [[ $log_file ]]; then
		log_fatal "$1"
	else
		echo "FATAL ERROR: $1"
	fi
}

#---------------------------------------------------------------------
## Returns an error if the variable in question is empty/not set
## @Note Works only for non-array variables
## @Type Private
## @param Variable name
## @param Extra error line(s) to append (optional, one parameter for each extra line)
#---------------------------------------------------------------------
config_validate_check_exists() {
	if [[ -z "${!1}" ]]; then
		config_dolog_fatal "YOU MUST SET $1 IN THE CONFIG"
		shift
		# Do the rest of the messages
		local line=
		for line in "$@"; do
			config_dolog_fatal "$line"
		done
		envbot_quit 2
	fi
}


#---------------------------------------------------------------------
## Validate config file
## @Type Private
#---------------------------------------------------------------------
config_validate() {
	# Note: normal logging is not initialized yet at this point,
	# so we use config_dolog_fatal, that calls normal logging in case
	# logging is loaded (like rehash).

	# General settings
	config_validate_check_exists config_firstnick
	config_validate_check_exists config_ident
	config_validate_check_exists config_gecos

	# Server settings
	config_validate_check_exists config_server
	config_validate_check_exists config_server_port
	config_validate_check_exists config_server_ssl

	# Logging
	config_validate_check_exists config_log_dir
	config_validate_check_exists config_log_stdout
	config_validate_check_exists config_log_raw
	config_validate_check_exists config_log_colors

	# Commands
	config_validate_check_exists config_commands_listenregex
	config_validate_check_exists config_commands_private_always

	# Feedback
	config_validate_check_exists config_feedback_unknown_commands

	# Access
	if [[ -z "${config_access_mask[1]}" ]]; then
		config_dolog_fatal "YOU MUST SET AT LEAST ONE OWNER IN EXAMPLE CONFIG"
		config_dolog_fatal "AND THAT OWNER MUST BE THE FIRST ONE (config_access_mask[1] that is)."
		envbot_quit 1
	fi
	if ! list_contains "config_access_capab[1]" "owner"; then
		config_dolog_fatal "YOU MUST SET AT LEAST ONE OWNER IN EXAMPLE CONFIG"
		config_dolog_fatal "AND THAT OWNER MUST BE THE FIRST ONE (config_access_capab[1] that is)."
		envbot_quit 1
	fi

	# Transports
	config_validate_check_exists "config_transport_dir"
	if [[ ! -d "${config_transport_dir}" ]]; then
		config_dolog_fatal "The transport directory ${config_transport_dir} doesn't seem to exist"
		envbot_quit 2
	fi
	config_validate_check_exists "config_transport"
	if [[ ! -r "${config_transport_dir}/${config_transport}.sh" ]]; then
		config_dolog_fatal "The transport ${config_transport} doesn't seem to exist"
		envbot_quit 2
	fi

	# Modules
	config_validate_check_exists config_modules_dir
	if ! [[ -d "$config_modules_dir" ]]; then
		if ! list_contains transport_supports "bind"; then
			config_dolog_fatal "$config_modules_dir DOES NOT EXIST OR IS NOT A DIRECTORY."
			envbot_quit 1
		fi
	fi
	config_validate_check_exists config_modules
}

#---------------------------------------------------------------------
## Validate some settings from config file that can only be done after
## transport was loaded.
## @Type Private
#---------------------------------------------------------------------
config_validate_transport() {
	# At this point logging is enabled, we can use it.
	if [[ $config_server_ssl -ne 0 ]]; then
		if ! list_contains transport_supports "ssl"; then
			log_fatal "THIS TRANSPORT DOES NOT SUPORT SSL"
			envbot_quit 1
		fi
	else
		if ! list_contains transport_supports "nossl"; then
			log_fatal "THIS TRANSPORT REQUIRES SSL"
			envbot_quit 1
		fi
	fi
	if [[ "$config_server_bind" ]]; then
		if ! list_contains transport_supports "bind"; then
			log_fatal "THIS TRANSPORT DOES NOT SUPORT BINDING AN IP"
			envbot_quit 1
		fi
	fi
}