Updated timestamps
[deliverable/titan.core.git] / mctr2 / mctr / main.cc
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 ******************************************************************************/
21 //
22 // Description: Implementation file for main
23 // Author: Vilmos Varga
24 // mail: ethvva@eth.ericsson.se
25 //
26 // Copyright (c) 2000-2015 Ericsson Telecom AB
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:
This page took 0.042575 seconds and 5 git commands to generate.