Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Bene, Tamas | |
12 | * Beres, Szabolcs | |
13 | * Czimbalmos, Eduard | |
14 | * Delic, Adam | |
15 | * Lovassy, Arpad | |
16 | * Raduly, Csaba | |
17 | * Szabados, Kristof | |
18 | * Szabo, Janos Zoltan – initial implementation | |
19 | * | |
20 | ******************************************************************************/ | |
970ed795 EL |
21 | // |
22 | // Description: Implementation file for main | |
23 | // Author: Vilmos Varga | |
24 | // mail: ethvva@eth.ericsson.se | |
25 | // | |
3abe9331 | 26 | // Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
27 | // |
28 | //---------------------------------------------------------------------------- | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <string.h> | |
32 | #include <stdlib.h> | |
33 | #include <dirent.h> | |
34 | #include <time.h> | |
35 | #include <unistd.h> | |
36 | ||
37 | // STL include stuff | |
38 | #include <string> | |
39 | #include <vector> | |
40 | #include <map> | |
41 | #include <iostream> | |
42 | #include <fstream> | |
43 | ||
44 | #include "../../common/memory.h" | |
45 | #include "../../common/path.h" | |
46 | #include "../../common/version_internal.h" | |
47 | ||
48 | #ifdef LICENSE | |
49 | #include "../../common/license.h" | |
50 | #endif | |
51 | ||
52 | #include "MainController.h" | |
53 | ||
54 | #if defined CLI | |
55 | #include "../cli/Cli.h" | |
56 | #else | |
57 | #error "CLI must be defined" | |
58 | #endif | |
59 | ||
60 | extern int config_read_debug; | |
61 | ||
62 | /* ASCII ART STUFF */ | |
63 | ||
64 | std::vector<std::string> split(const char separator, const std::string& source_str, bool drop_empty=true) | |
65 | { | |
66 | std::vector<std::string> str_vec; | |
67 | const char* begin_pos = source_str.data(); | |
68 | const char* end_pos = begin_pos + source_str.length(); // points behind the last char | |
69 | for (const char* act_pos = begin_pos; act_pos<end_pos; act_pos++) | |
70 | { | |
71 | if ( *act_pos==separator ) | |
72 | { | |
73 | if (!drop_empty || (act_pos>begin_pos)) | |
74 | str_vec.push_back(std::string(begin_pos, act_pos-begin_pos)); | |
75 | begin_pos = act_pos+1; | |
76 | } | |
77 | } | |
78 | if (!drop_empty || (end_pos>begin_pos)) str_vec.push_back(std::string(begin_pos, end_pos-begin_pos)); | |
79 | return str_vec; | |
80 | } | |
81 | ||
82 | std::vector<std::string> get_directory_files(const std::string& directory) | |
83 | { | |
84 | std::vector<std::string> file_list; | |
85 | DIR *dir = opendir(directory.c_str()); | |
86 | if (dir==NULL) return file_list; | |
87 | struct dirent *ent; | |
88 | while ((ent=readdir(dir))!=NULL) { | |
89 | std::string file_name = ent->d_name; | |
90 | if (get_path_status((directory+"/"+file_name).c_str())==PS_FILE) file_list.push_back(file_name); | |
91 | } | |
92 | closedir(dir); | |
93 | return file_list; | |
94 | } | |
95 | ||
96 | void print_ascii_art(const std::string& file_path) | |
97 | { | |
98 | try { | |
99 | std::ifstream ifs(file_path.c_str(), std::ifstream::in); | |
100 | while (ifs.good()) { | |
101 | int c = (char)ifs.get(); | |
102 | if (c<0) c = '\n'; | |
103 | std::cout << (char)c; | |
104 | } | |
105 | ifs.close(); | |
106 | } | |
107 | catch (...) { /* stfu */ } | |
108 | } | |
109 | ||
110 | struct current_condition_data | |
111 | { | |
112 | std::string user; | |
113 | struct tm time; | |
114 | current_condition_data(); | |
115 | }; | |
116 | current_condition_data::current_condition_data() | |
117 | { | |
118 | const char* user_name = getlogin(); // TODO: use getpwuid(getuid()) | |
119 | user = user_name ? std::string(user_name) : ""; | |
120 | time_t rawtime; | |
121 | ::time(&rawtime); | |
122 | struct tm * curr_tm = localtime(&rawtime); | |
123 | time = *curr_tm; | |
124 | } | |
125 | ||
126 | typedef bool (*condition_function)(const std::string& value, const current_condition_data& curr_data); | |
127 | typedef std::map<std::string,condition_function> condition_map; | |
128 | ||
129 | bool condition_user(const std::string& value, const current_condition_data& curr_data) | |
130 | { | |
131 | return value==curr_data.user; | |
132 | } | |
133 | ||
134 | // sets the interval or returns false if invalid input | |
135 | bool get_interval(const std::string& value, int& a, int& b) | |
136 | { | |
137 | std::vector<std::string> nums = split('_', value); | |
138 | switch (nums.size()) { | |
139 | case 1: | |
140 | a = b = atoi(nums[0].c_str()); | |
141 | return true; | |
142 | case 2: | |
143 | a = atoi(nums[0].c_str()); | |
144 | b = atoi(nums[1].c_str()); | |
145 | return true; | |
146 | default: ; | |
147 | } | |
148 | return false; | |
149 | } | |
150 | ||
151 | bool is_in_interval(const std::string& interval, int i) | |
152 | { | |
153 | int a,b; | |
154 | if (!get_interval(interval, a, b)) return false; | |
155 | return a<=i && i<=b; | |
156 | } | |
157 | ||
158 | bool condition_weekday(const std::string& value, const current_condition_data& curr_data) | |
159 | { | |
160 | return is_in_interval(value, curr_data.time.tm_wday ? curr_data.time.tm_wday : 7); // 1 - 7 | |
161 | } | |
162 | ||
163 | bool condition_day(const std::string& value, const current_condition_data& curr_data) | |
164 | { | |
165 | return is_in_interval(value, curr_data.time.tm_mday); // 1 - 31 | |
166 | } | |
167 | ||
168 | bool condition_month(const std::string& value, const current_condition_data& curr_data) | |
169 | { | |
170 | return is_in_interval(value, curr_data.time.tm_mon+1); // 1 - 12 | |
171 | } | |
172 | ||
173 | bool condition_year(const std::string& value, const current_condition_data& curr_data) | |
174 | { | |
175 | return is_in_interval(value, curr_data.time.tm_year+1900); | |
176 | } | |
177 | ||
178 | bool condition_hour(const std::string& value, const current_condition_data& curr_data) | |
179 | { | |
180 | return is_in_interval(value, curr_data.time.tm_hour); // 0 - 23 | |
181 | } | |
182 | ||
183 | bool condition_minute(const std::string& value, const current_condition_data& curr_data) | |
184 | { | |
185 | return is_in_interval(value, curr_data.time.tm_min); // 0 - 59 | |
186 | } | |
187 | ||
188 | bool condition_second(const std::string& value, const current_condition_data& curr_data) | |
189 | { | |
190 | return is_in_interval(value, curr_data.time.tm_sec); // 0 - 61 | |
191 | } | |
192 | ||
193 | condition_map create_condition_map() | |
194 | { | |
195 | condition_map cond_map; | |
196 | cond_map.insert(make_pair("user",condition_user)); | |
197 | cond_map.insert(make_pair("weekday",condition_weekday)); | |
198 | cond_map.insert(make_pair("day",condition_day)); | |
199 | cond_map.insert(make_pair("month",condition_month)); | |
200 | cond_map.insert(make_pair("year",condition_year)); | |
201 | cond_map.insert(make_pair("hour",condition_hour)); | |
202 | cond_map.insert(make_pair("minute",condition_minute)); | |
203 | cond_map.insert(make_pair("second",condition_second)); | |
204 | return cond_map; | |
205 | } | |
206 | ||
207 | // display random ascii art, if there was an error don't report it | |
208 | void display_ascii_art() | |
209 | { | |
210 | std::string asciiart_dir; | |
211 | const char* ttcn3_asciiart_dir = getenv("TTCN3_ASCIIART_DIR"); | |
212 | if (ttcn3_asciiart_dir!=NULL) { | |
213 | if (strlen(ttcn3_asciiart_dir)==0) return; | |
214 | asciiart_dir = ttcn3_asciiart_dir; | |
215 | } else { | |
216 | const char* ttcn3_dir = getenv("TTCN3_DIR"); | |
217 | asciiart_dir = ttcn3_dir ? ttcn3_dir : ""; | |
218 | asciiart_dir += (asciiart_dir.size()>0 && asciiart_dir[asciiart_dir.size()-1]=='/') ? "" : "/"; | |
219 | asciiart_dir += "etc/asciiart"; | |
220 | } | |
221 | if (get_path_status(asciiart_dir.c_str())!=PS_DIRECTORY) return; | |
222 | std::vector<std::string> asciiart_files = get_directory_files(asciiart_dir); | |
223 | std::vector<std::string> normal_active_files; // files that don't have special filter | |
224 | std::vector<std::string> special_active_files; // files that have special filter | |
225 | condition_map cond_map = create_condition_map(); | |
226 | current_condition_data curr_data; // calculate current data for conditions only once, before entering loops | |
227 | for (std::vector<std::string>::iterator file_name_i = asciiart_files.begin(); file_name_i<asciiart_files.end(); file_name_i++) { | |
228 | std::vector<std::string> file_name_parts = split('.', *file_name_i); | |
229 | bool is_special = false; | |
230 | bool is_active = true; | |
231 | for (std::vector<std::string>::iterator name_part_i = file_name_parts.begin(); name_part_i<file_name_parts.end(); name_part_i++) { | |
232 | std::vector<std::string> condition = split('-', *name_part_i); | |
233 | if (condition.size()==2) { | |
234 | const std::string& cond_name = condition[0]; | |
235 | const std::string& cond_value = condition[1]; | |
236 | condition_map::iterator cond_iter = cond_map.find(cond_name); | |
237 | if (cond_iter!=cond_map.end()) { | |
238 | is_special = true; | |
239 | is_active = is_active && (cond_iter->second)(cond_value, curr_data); | |
240 | } | |
241 | } | |
242 | } | |
243 | if (is_active) { | |
244 | if (is_special) special_active_files.push_back(*file_name_i); | |
245 | else normal_active_files.push_back(*file_name_i); | |
246 | } | |
247 | } | |
248 | srand(time(NULL)); | |
249 | if (special_active_files.size()>0) { | |
250 | print_ascii_art(asciiart_dir + "/" + special_active_files[rand()%special_active_files.size()]); | |
251 | } else if (normal_active_files.size()>0) { | |
252 | print_ascii_art(asciiart_dir + "/" + normal_active_files[rand()%normal_active_files.size()]); | |
253 | } | |
254 | } | |
255 | ||
256 | /* Main function */ | |
257 | ||
258 | using namespace mctr; | |
259 | ||
260 | int main(int argc, char *argv[]) | |
261 | { | |
262 | #ifndef NDEBUG | |
263 | config_read_debug = (getenv("DEBUG_CONFIG") != NULL); | |
264 | #endif | |
265 | ||
266 | display_ascii_art(); | |
267 | ||
268 | if (argc == 2 && !strcmp(argv[1], "-v")) { | |
269 | fputs("Main Controller " | |
270 | #if defined CLI | |
271 | "(CLI)" | |
272 | #endif | |
273 | " for the TTCN-3 Test Executor\n" | |
274 | "Product number: " PRODUCT_NUMBER "\n" | |
275 | "Build date: " __DATE__ " " __TIME__ "\n" | |
276 | "Compiled with: " C_COMPILER_VERSION "\n\n" | |
277 | COPYRIGHT_STRING "\n\n", stderr); | |
278 | #ifdef LICENSE | |
279 | print_license_info(); | |
280 | fputs("\nUsing ", stderr); | |
281 | fputs(openssl_version_str(), stderr); | |
282 | fputs("\n\n", stderr); | |
283 | #endif | |
284 | return 0; | |
285 | } | |
286 | ||
287 | int max_ptcs; | |
288 | #ifdef LICENSE | |
289 | license_struct lstr; | |
290 | init_openssl(); | |
291 | load_license(&lstr); | |
292 | if (!verify_license(&lstr)) { | |
293 | free_license(&lstr); | |
294 | free_openssl(); | |
295 | exit(EXIT_FAILURE); | |
296 | } | |
297 | if (!check_feature(&lstr, FEATURE_MCTR)) { | |
298 | fputs("The license key does not allow the starting of TTCN-3 " | |
299 | "Main Controller.\n", stderr); | |
300 | return 2; | |
301 | } | |
302 | max_ptcs = lstr.max_ptcs; | |
303 | free_license(&lstr); | |
304 | free_openssl(); | |
305 | #else | |
306 | max_ptcs = -1; | |
307 | #endif | |
308 | int ret_val; | |
309 | { | |
310 | #if defined CLI | |
311 | cli::Cli | |
312 | #endif | |
313 | userInterface; | |
314 | ||
315 | userInterface.initialize(); | |
316 | MainController::initialize(userInterface, max_ptcs); | |
317 | ||
318 | ret_val = userInterface.enterLoop(argc, argv); | |
319 | ||
320 | MainController::terminate(); | |
321 | } | |
322 | check_mem_leak(argv[0]); | |
323 | ||
324 | return ret_val; | |
325 | } | |
326 | ||
327 | // Local Variables: | |
328 | // mode: C++ | |
329 | // indent-tabs-mode: nil | |
330 | // c-basic-offset: 2 | |
331 | // End: |