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
18 * Szabo, Janos Zoltan – initial implementation
20 ******************************************************************************/
22 // Description: Implementation file for main
23 // Author: Vilmos Varga
24 // mail: ethvva@eth.ericsson.se
26 // Copyright (c) 2000-2015 Ericsson Telecom AB
28 //----------------------------------------------------------------------------
44 #include "../../common/memory.h"
45 #include "../../common/path.h"
46 #include "../../common/version_internal.h"
49 #include "../../common/license.h"
52 #include "MainController.h"
55 #include "../cli/Cli.h"
57 #error "CLI must be defined"
60 extern int config_read_debug
;
64 std::vector
<std::string
> split(const char separator
, const std::string
& source_str
, bool drop_empty
=true)
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
++)
71 if ( *act_pos
==separator
)
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;
78 if (!drop_empty
|| (end_pos
>begin_pos
)) str_vec
.push_back(std::string(begin_pos
, end_pos
-begin_pos
));
82 std::vector
<std::string
> get_directory_files(const std::string
& directory
)
84 std::vector
<std::string
> file_list
;
85 DIR *dir
= opendir(directory
.c_str());
86 if (dir
==NULL
) return file_list
;
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
);
96 void print_ascii_art(const std::string
& file_path
)
99 std::ifstream
ifs(file_path
.c_str(), std::ifstream::in
);
101 int c
= (char)ifs
.get();
103 std::cout
<< (char)c
;
107 catch (...) { /* stfu */ }
110 struct current_condition_data
114 current_condition_data();
116 current_condition_data::current_condition_data()
118 const char* user_name
= getlogin(); // TODO: use getpwuid(getuid())
119 user
= user_name
? std::string(user_name
) : "";
122 struct tm
* curr_tm
= localtime(&rawtime
);
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
;
129 bool condition_user(const std::string
& value
, const current_condition_data
& curr_data
)
131 return value
==curr_data
.user
;
134 // sets the interval or returns false if invalid input
135 bool get_interval(const std::string
& value
, int& a
, int& b
)
137 std::vector
<std::string
> nums
= split('_', value
);
138 switch (nums
.size()) {
140 a
= b
= atoi(nums
[0].c_str());
143 a
= atoi(nums
[0].c_str());
144 b
= atoi(nums
[1].c_str());
151 bool is_in_interval(const std::string
& interval
, int i
)
154 if (!get_interval(interval
, a
, b
)) return false;
158 bool condition_weekday(const std::string
& value
, const current_condition_data
& curr_data
)
160 return is_in_interval(value
, curr_data
.time
.tm_wday
? curr_data
.time
.tm_wday
: 7); // 1 - 7
163 bool condition_day(const std::string
& value
, const current_condition_data
& curr_data
)
165 return is_in_interval(value
, curr_data
.time
.tm_mday
); // 1 - 31
168 bool condition_month(const std::string
& value
, const current_condition_data
& curr_data
)
170 return is_in_interval(value
, curr_data
.time
.tm_mon
+1); // 1 - 12
173 bool condition_year(const std::string
& value
, const current_condition_data
& curr_data
)
175 return is_in_interval(value
, curr_data
.time
.tm_year
+1900);
178 bool condition_hour(const std::string
& value
, const current_condition_data
& curr_data
)
180 return is_in_interval(value
, curr_data
.time
.tm_hour
); // 0 - 23
183 bool condition_minute(const std::string
& value
, const current_condition_data
& curr_data
)
185 return is_in_interval(value
, curr_data
.time
.tm_min
); // 0 - 59
188 bool condition_second(const std::string
& value
, const current_condition_data
& curr_data
)
190 return is_in_interval(value
, curr_data
.time
.tm_sec
); // 0 - 61
193 condition_map
create_condition_map()
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
));
207 // display random ascii art, if there was an error don't report it
208 void display_ascii_art()
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
;
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";
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()) {
239 is_active
= is_active
&& (cond_iter
->second
)(cond_value
, curr_data
);
244 if (is_special
) special_active_files
.push_back(*file_name_i
);
245 else normal_active_files
.push_back(*file_name_i
);
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()]);
258 using namespace mctr
;
260 int main(int argc
, char *argv
[])
263 config_read_debug
= (getenv("DEBUG_CONFIG") != NULL
);
268 if (argc
== 2 && !strcmp(argv
[1], "-v")) {
269 fputs("Main Controller "
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
);
279 print_license_info();
280 fputs("\nUsing ", stderr
);
281 fputs(openssl_version_str(), stderr
);
282 fputs("\n\n", stderr
);
292 if (!verify_license(&lstr
)) {
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
);
302 max_ptcs
= lstr
.max_ptcs
;
315 userInterface
.initialize();
316 MainController::initialize(userInterface
, max_ptcs
);
318 ret_val
= userInterface
.enterLoop(argc
, argv
);
320 MainController::terminate();
322 check_mem_leak(argv
[0]);
329 // indent-tabs-mode: nil